module klang.编译.APFloat.APFoat_;
import 全局;
import std.conv: ·to = to;
import std.typecons: ·Tuple = Tuple, ·tuple = tuple;
import klang.编译.核心.核心_: 创建数组, 返回零值, 最小, 最大, rangeEquals, 开始包含, 字节转换, hexDigitValue, bitTo;
import 编译数字 = 编译数字.编译;
import klang.编译.APSInt.APSInt_: APSInt_;
import klang.编译.APInt.APInt_: INT_MAX, INT_MIN, WordType_, APINT_BITS_PER_WORD, tcSet, tcSetBit, tcExtractBit, tcMSB, tcLSB, NextPowerOf2, tcExtract, tcSetLeastSignificantBits, tcIsZero, tcShiftLeft, tcShiftRight, tcAssign, tcClearBit, tcCompare, tcSubtract, tcNegate, tcMultiplyPart, tcFullMultiply, APInt_, udivrem, udivrem_2, Op负, tcIncrement, tcAdd, floatToBits, doubleToBits, getAllOnesValue;
import klang.编译.类型.枚举值.枚举值_: 字符_;
alias ExponentType_ = int;
alias IntegerPart_ = ulong;
ulong integerPartWidth;
klang.编译.APFloat.APFoat_.FltSemantics_ semIEEEhalf;
klang.编译.APFloat.APFoat_.FltSemantics_ semBFloat;
klang.编译.APFloat.APFoat_.FltSemantics_ semIEEEsingle;
klang.编译.APFloat.APFoat_.FltSemantics_ semIEEEdouble;
klang.编译.APFloat.APFoat_.FltSemantics_ semIEEEquad;
klang.编译.APFloat.APFoat_.FltSemantics_ semX87DoubleExtended;
klang.编译.APFloat.APFoat_.FltSemantics_ semPPCDoubleDouble;
klang.编译.APFloat.APFoat_.FltSemantics_ semBogus;
klang.编译.APFloat.APFoat_.FltSemantics_ semPPCDoubleDoubleLegacy;
klang.编译.APFloat.APFoat_.RoundingMode_ rmNearestTiesToEven = RoundingMode_.NearestTiesToEven;
klang.编译.APFloat.APFoat_.RoundingMode_ rmTowardPositive = RoundingMode_.TowardPositive;
klang.编译.APFloat.APFoat_.RoundingMode_ rmTowardNegative = RoundingMode_.TowardNegative;
klang.编译.APFloat.APFoat_.RoundingMode_ rmTowardZero = RoundingMode_.TowardZero;
klang.编译.APFloat.APFoat_.RoundingMode_ rmNearestTiesToAway = RoundingMode_.NearestTiesToAway;
int maxExponent = 16383;
int maxPrecision = 113;
uint maxPowerOfFiveExponent;
uint maxPowerOfFiveParts;
static this() {
    integerPartWidth = APINT_BITS_PER_WORD;
    semIEEEhalf = new klang.编译.APFloat.APFoat_.FltSemantics_(15, 14, 11, 16);
    semBFloat = new klang.编译.APFloat.APFoat_.FltSemantics_(127, -126, 8, 16);
    semIEEEsingle = new klang.编译.APFloat.APFoat_.FltSemantics_(127, -126, 24, 32);
    semIEEEdouble = new klang.编译.APFloat.APFoat_.FltSemantics_(1023, -1022, 53, 64);
    semIEEEquad = new klang.编译.APFloat.APFoat_.FltSemantics_(16383, -16382, 113, 128);
    semX87DoubleExtended = new klang.编译.APFloat.APFoat_.FltSemantics_(16383, -16382, 64, 80);
    semPPCDoubleDouble = new klang.编译.APFloat.APFoat_.FltSemantics_(-1, 0, 0, 128);
    semBogus = new klang.编译.APFloat.APFoat_.FltSemantics_(0, 0, 0, 0);
    semPPCDoubleDoubleLegacy = new klang.编译.APFloat.APFoat_.FltSemantics_(1023, -1022 + 53, 53 + 53, 128);
    maxPowerOfFiveExponent = 16383 + 113 - 1;
    maxPowerOfFiveParts = (cast(uint)(2 + (((16383 + 113 - 1) * 815) / (351 * .integerPartWidth))));
}
enum Semantics_ : int {
    S_None = 0,
    S_IEEEhalf = 1,
    S_BFloat = 2,
    S_IEEEsingle = 3,
    S_IEEEdouble = 4,
    S_x87DoubleExtended = 5,
    S_IEEEquad = 6,
    S_PPCDoubleDouble = 7
}
enum CmpResult_ : int {
    cmpLessThan = 0,
    cmpEqual = 1,
    cmpGreaterThan = 2,
    cmpUnordered = 3
}
enum RoundingMode_ : byte {
    // Rounding mode defined in IEEE-754.
    TowardZero = 0,
    NearestTiesToEven = 1,
    TowardPositive = 2,
    TowardNegative = 3,
    NearestTiesToAway = 4,
    // Special values.
    Dynamic = 7,
    Invalid = -1 ///< Denotes invalid value.
}
enum OpStatus_ : uint {
    opOK = 0u,
    opInvalidOp = 1u,
    opDivByZero = 2u,
    opOverflow = 4u,
    opUnderflow = 8u,
    opInexact = 16u
}
/// Category of internally-represented number.
enum FltCategory_ : int {
    fcInfinity = 0,
    fcNaN = 1,
    fcNormal = 2,
    fcZero = 3
}
/// Convenience enum used to construct an uninitialized APFloat.
enum UninitializedTag_ : int {
    uninitialized = 0
}
/// Enumeration of \c ilogb error results.
enum IlogbErrorKinds_ : int {
    IEK_Zero = -2147483647,
    IEK_NaN = -2147483648,
    IEK_Inf = 2147483647
}
enum LostFraction_ : int {
    lfExactlyZero = 0,
    lfLessThanHalf = 1,
    lfExactlyHalf = 2,
    lfMoreThanHalf = 3 // 1xxxxx  x's not all zero
}
class FltSemantics_ {
    int maxExponent;
    int minExponent;
    uint precision;
    uint sizeInBits;
    this() {
        this.maxExponent = 0;
        this.minExponent = 0;
        this.precision = 0;
        this.sizeInBits = 0;
    }
    this(int maxExponent, int minExponent, uint precision, uint sizeInBits) {
        this.maxExponent = maxExponent;
        this.minExponent = minExponent;
        this.precision = precision;
        this.sizeInBits = sizeInBits;
    }
    bool isRepresentableBy(FltSemantics_ S) {
        return this.maxExponent <= S.maxExponent && this.minExponent >= S.minExponent && this.precision <= S.precision;
    }
}
class APFloatBase_ {
    FltSemantics_ semantics;
    this() {
        this.semantics = ··null!(FltSemantics_);
    }
}
class IEEEFloat_ : APFloatBase_ {
    ulong[] significand;
    int exponent;
    FltCategory_ category;
    uint sign;
    this() {
        super();
        this.significand = 创建数组!(ulong)();
        this.significand.length = 1;
        this.exponent = ··null!(int);
        this.category = FltCategory_.fcZero;
        this.sign = 1;
    }
    this(FltSemantics_ ourSemantics, ulong value) {
        this();
        this.initialize(ourSemantics);
        this.zeroSignificand();
        this.significand[0] = value;
        this.exponent = ourSemantics.precision - 1;
        this.category = FltCategory_.fcNormal;
        this.sign = 0;
        this.normalize(RoundingMode_.NearestTiesToEven, LostFraction_.lfExactlyZero);
    }
    this(FltSemantics_ ourSemantics) {
        this();
        this.initialize(ourSemantics);
        this.makeZero(false);
    }
    this(FltSemantics_ ourSemantics, UninitializedTag_ tag) {
        this(ourSemantics);
    }
    this(FltSemantics_ semantics, APInt_ I) {
        this();
        this.initFromAPInt(semantics, I);
    }
    this(float f) {
        this();
        this.initFromAPInt(.semIEEEsingle, floatToBits(f));
    }
    this(double d) {
        this();
        this.initFromAPInt(.semIEEEdouble, doubleToBits(d));
    }
    this(IEEEFloat_ rhs) {
        this();
        this.initialize(rhs.semantics);
        this.assign(rhs);
    }
    void initialize(FltSemantics_ ourSemantics) {
        uint count = 0;
        this.semantics = ourSemantics;
        count = this.partCount();
        if (count > 1) {
            this.significand.length = count;
        }
    }
    void initFromAPInt(FltSemantics_ Sem, APInt_ api) {
        if (Sem == .semIEEEhalf) {
            return this.initFromHalfAPInt(api);
        }
        if (Sem == .semBFloat) {
            return this.initFromBFloatAPInt(api);
        }
        if (Sem == .semIEEEsingle) {
            return this.initFromFloatAPInt(api);
        }
        if (Sem == .semIEEEdouble) {
            return this.initFromDoubleAPInt(api);
        }
        if (Sem == .semX87DoubleExtended) {
            return this.initFromF80LongDoubleAPInt(api);
        }
        if (Sem == .semIEEEquad) {
            return this.initFromQuadrupleAPInt(api);
        }
        if (Sem == .semPPCDoubleDoubleLegacy) {
            return this.initFromPPCDoubleDoubleAPInt(api);
        }
    }
    void initFromHalfAPInt(APInt_ api) {
        uint i = (cast(uint)(api.U[0]));
        uint myexponent = (i >> 10) & 31;
        uint mysignificand = i & 1023;
        this.initialize(.semIEEEhalf);
        this.sign = i >> 15;
        if (myexponent == 0 && mysignificand == 0) {
            this.makeZero(this.sign != 0);
        }
        else if (myexponent == 31 && mysignificand == 0) {
            this.makeInf(this.sign != 0);
        }
        else if (myexponent == 31 && mysignificand != 0) {
            this.category = FltCategory_.fcNaN;
            this.exponent = this.exponentNaN();
            this.significand[0] = mysignificand;
        }
        else {
            this.category = FltCategory_.fcNormal;
            this.exponent = (cast(int)(myexponent - 15)); //bias
            this.significand[0] = mysignificand;
            if (myexponent == 0) { // denormal
                this.exponent = -14;
            }
            else {
                this.significand[0] |= 1024; // integer bit
            }
        }
    }
    void initFromBFloatAPInt(APInt_ api) {
        uint i = (cast(uint)(api.U[0]));
        uint myexponent = (i >> 7) & 255;
        uint mysignificand = i & 127;
        this.initialize(.semBFloat);
        this.sign = i >> 15;
        if (myexponent == 0 && mysignificand == 0) {
            this.makeZero(this.sign != 0);
        }
        else if (myexponent == 255 && mysignificand == 0) {
            this.makeInf(this.sign != 0);
        }
        else if (myexponent == 255 && mysignificand != 0) {
            this.category = FltCategory_.fcNaN;
            this.exponent = this.exponentNaN();
            this.significand[0] = mysignificand;
        }
        else {
            this.category = FltCategory_.fcNormal;
            this.exponent = (cast(int)(myexponent - 127)); // bias
            this.significand[0] = mysignificand;
            if (myexponent == 0) { // denormal
                this.exponent = -126;
            }
            else {
                this.significand[0] |= 128; // integer bit
            }
        }
    }
    void initFromFloatAPInt(APInt_ api) {
        uint i = (cast(uint)(api.U[0]));
        uint myexponent = (i >> 23) & 255;
        uint mysignificand = i & 8388607;
        this.initialize(.semIEEEsingle);
        this.sign = i >> 31;
        if (myexponent == 0 && mysignificand == 0) {
            this.makeZero(this.sign != 0);
        }
        else if (myexponent == 255 && mysignificand == 0) {
            this.makeInf(this.sign != 0);
        }
        else if (myexponent == 255 && mysignificand != 0) {
            this.category = FltCategory_.fcNaN;
            this.exponent = this.exponentNaN();
            this.significand[0] = mysignificand;
        }
        else {
            this.category = FltCategory_.fcNormal;
            this.exponent = (cast(int)(myexponent - 127)); //bias
            this.significand[0] = mysignificand;
            if (myexponent == 0) {
                this.exponent = -126;
            }
            else {
                this.significand[0] |= 8388608; // integer bit
            }
        }
    }
    void initFromDoubleAPInt(APInt_ api) {
        ulong i = api.U[0];
        ulong myexponent = (i >> 52) & 2047;
        ulong mysignificand = i & 4503599627370495uL;
        this.initialize(.semIEEEdouble);
        this.sign = (cast(uint)(i >> 63));
        if (myexponent == 0 && mysignificand == 0) {
            this.makeZero(this.sign != 0);
        }
        else if (myexponent == 2047 && mysignificand == 0) {
            this.makeInf(this.sign != 0);
        }
        else if (myexponent == 2047 && mysignificand != 0) {
            this.category = FltCategory_.fcNaN;
            this.exponent = this.exponentNaN();
            this.significand[0] = mysignificand;
        }
        else {
            this.category = FltCategory_.fcNormal;
            this.exponent = (cast(int)(myexponent - 1023));
            this.significand[0] = mysignificand;
            if (myexponent == 0) {
                this.exponent = -1022;
            }
            else {
                this.significand[0] |= 4503599627370496uL; // integer bit
            }
        }
    }
    void initFromF80LongDoubleAPInt(APInt_ api) {
        ulong i1 = api.getRawData()[0];
        ulong i2 = api.getRawData()[1];
        ulong myexponent = (i2 & 32767);
        ulong mysignificand = i1;
        ubyte myintegerbit = (cast(ubyte)(mysignificand >> 63));
        this.initialize(.semX87DoubleExtended);
        this.sign = (cast(uint)(i2 >> 15));
        if (myexponent == 0 && mysignificand == 0) {
            this.makeZero(this.sign != 0);
        }
        else if (myexponent == 32767 && mysignificand == 9223372036854775808uL) {
            this.makeInf(this.sign != 0);
        }
        else if ((myexponent == 32767 && mysignificand != 9223372036854775808uL) || (myexponent != 32767 && myexponent != 0 && myintegerbit == 0)) {
            this.category = FltCategory_.fcNaN;
            this.exponent = this.exponentNaN();
            this.significand[0] = mysignificand;
            this.significand[1] = 0;
        }
        else {
            this.category = FltCategory_.fcNormal;
            this.exponent = (cast(int)(myexponent - 16383));
            this.significand[0] = mysignificand;
            this.significand[1] = 0;
            if (myexponent == 0) {
                this.exponent = -16382;
            }
        }
    }
    void initFromQuadrupleAPInt(APInt_ api) {
        ulong i1 = api.getRawData()[0];
        ulong i2 = api.getRawData()[1];
        ulong myexponent = (i2 >> 48) & 32767;
        ulong mysignificand = i1;
        ulong mysignificand2 = i2 & 281474976710655L;
        this.initialize(.semIEEEquad);
        this.sign = (cast(uint)(i2 >> 63));
        if (myexponent == 0 && (mysignificand == 0 && mysignificand2 == 0)) {
            this.makeZero(this.sign != 0);
        }
        else if (myexponent == 32767 && (mysignificand == 0 && mysignificand2 == 0)) {
            this.makeInf(this.sign != 0);
        }
        else if (myexponent == 32767 && (mysignificand != 0 || mysignificand2 != 0)) {
            this.category = FltCategory_.fcNaN;
            this.exponent = this.exponentNaN();
            this.significand[0] = mysignificand;
            this.significand[1] = mysignificand2;
        }
        else {
            this.category = FltCategory_.fcNormal;
            this.exponent = (cast(int)(myexponent - 16383));
            this.significand[0] = mysignificand;
            this.significand[1] = mysignificand2;
            if (myexponent == 0) {
                this.exponent = -16382;
            }
            else {
                this.significand[1] |= 281474976710656L; // integer bit
            }
        }
    }
    void initFromPPCDoubleDoubleAPInt(APInt_ api) {
        ulong i1 = api.getRawData()[0];
        ulong i2 = api.getRawData()[1];
        OpStatus_ fs = OpStatus_.opOK;
        bool losesInfo = false;
        // Get the first double and convert to our format.
        this.initFromDoubleAPInt(new APInt_(64, i1));
        fs = this.convert(.semPPCDoubleDoubleLegacy, .rmNearestTiesToEven, losesInfo);
        // Unless we have a special case, add in second double.
        if (this.isFiniteNonZero()) {
            IEEEFloat_ v = new IEEEFloat_(.semIEEEdouble, new APInt_(64, i2));
            fs = this.convert(.semPPCDoubleDoubleLegacy, .rmNearestTiesToEven, losesInfo);
            this.add(v, .rmNearestTiesToEven);
        }
    }
    APInt_ bitcastToAPInt() {
        if (this.semantics == .semIEEEhalf) {
            return this.convertHalfAPFloatToAPInt();
        }
        if (this.semantics == .semBFloat) {
            return this.convertBFloatAPFloatToAPInt();
        }
        if (this.semantics == .semIEEEsingle) {
            return this.convertFloatAPFloatToAPInt();
        }
        if (this.semantics == .semIEEEdouble) {
            return this.convertDoubleAPFloatToAPInt();
        }
        if (this.semantics == .semIEEEquad) {
            return this.convertQuadrupleAPFloatToAPInt();
        }
        if (this.semantics == .semPPCDoubleDoubleLegacy) {
            return this.convertPPCDoubleDoubleAPFloatToAPInt();
        }
        return this.convertF80LongDoubleAPFloatToAPInt();
    }
    APInt_ convertHalfAPFloatToAPInt() {
        uint myexponent = 0;
        uint mysignificand = 0;
        if (this.isFiniteNonZero()) {
            myexponent = this.exponent + 15; //bias
            mysignificand = (cast(uint[])(this.significandParts()))[0];
            if (myexponent == 1 && (mysignificand & 1024) == 0) {
                myexponent = 0;
            } // denormal
        }
        else if (this.category == FltCategory_.fcZero) {
            myexponent = 0;
            mysignificand = 0;
        }
        else if (this.category == FltCategory_.fcInfinity) {
            myexponent = 31;
            mysignificand = 0;
        }
        else {
            myexponent = 31;
            mysignificand = (cast(uint[])(this.significandParts()))[0];
        }
        return new APInt_(16, (cast(ulong)((((this.sign & 1) << 15) | ((myexponent & 31) << 10) | (mysignificand & 1023)))));
    }
    APInt_ convertBFloatAPFloatToAPInt() {
        uint myexponent = 0;
        uint mysignificand = 0;
        if (this.isFiniteNonZero()) {
            myexponent = this.exponent + 127; // bias
            mysignificand = (cast(uint[])(this.significandParts()))[0];
            if (myexponent == 1 && (mysignificand & 128) == 0) {
                myexponent = 0;
            } // denormal
        }
        else if (this.category == FltCategory_.fcZero) {
            myexponent = 0;
            mysignificand = 0;
        }
        else if (this.category == FltCategory_.fcInfinity) {
            myexponent = 255;
            mysignificand = 0;
        }
        else {
            myexponent = 255;
            mysignificand = (cast(uint[])(this.significandParts()))[0];
        }
        return new APInt_(16, (cast(ulong)((((this.sign & 1) << 15) | ((myexponent & 255) << 7) | (mysignificand & 127)))));
    }
    APInt_ convertFloatAPFloatToAPInt() {
        uint myexponent = 0;
        uint mysignificand = 0;
        if (this.isFiniteNonZero()) {
            myexponent = this.exponent + 127; //bias
            mysignificand = (cast(uint[])(this.significandParts()))[0];
            if (myexponent == 1 && (mysignificand & 8388608) == 0) {
                myexponent = 0;
            } // denormal
        }
        else if (this.category == FltCategory_.fcZero) {
            myexponent = 0;
            mysignificand = 0;
        }
        else if (this.category == FltCategory_.fcInfinity) {
            myexponent = 255;
            mysignificand = 0;
        }
        else {
            myexponent = 255;
            mysignificand = (cast(uint[])(this.significandParts()))[0];
        }
        return new APInt_(32, (cast(ulong)((((this.sign & 1) << 31) | ((myexponent & 255) << 23) | (mysignificand & 8388607)))));
    }
    APInt_ convertDoubleAPFloatToAPInt() {
        ulong myexponent = 0;
        ulong mysignificand = 0;
        if (this.isFiniteNonZero()) {
            myexponent = this.exponent + 1023; //bias
            mysignificand = this.significandParts()[0];
            if (myexponent == 1 && (mysignificand & 4503599627370496L) == 0) {
                myexponent = 0;
            } // denormal
        }
        else if (this.category == FltCategory_.fcZero) {
            myexponent = 0;
            mysignificand = 0;
        }
        else if (this.category == FltCategory_.fcInfinity) {
            myexponent = 2047;
            mysignificand = 0;
        }
        else {
            myexponent = 2047;
            mysignificand = this.significandParts()[0];
        }
        return new APInt_(64, (cast(ulong)((((cast(ulong)(this.sign & 1)) << 63) | ((myexponent & 2047) << 52) | (mysignificand & 4503599627370495L)))));
    }
    APInt_ convertF80LongDoubleAPFloatToAPInt() {
        ulong myexponent = 0;
        ulong mysignificand = 0;
        if (this.isFiniteNonZero()) {
            myexponent = this.exponent + 16383; //bias
            mysignificand = this.significandParts()[0];
            if (myexponent == 1 && (mysignificand & 9223372036854775808uL) == 0) {
                myexponent = 0;
            } // denormal
        }
        else if (this.category == FltCategory_.fcZero) {
            myexponent = 0;
            mysignificand = 0;
        }
        else if (this.category == FltCategory_.fcInfinity) {
            myexponent = 32767;
            mysignificand = 9223372036854775808uL;
        }
        else {
            myexponent = 32767;
            mysignificand = this.significandParts()[0];
        }
        ulong[2] words = [0, 0];
        words[0] = mysignificand;
        words[1] = (cast(ulong)(((cast(ulong)(this.sign & 1)) << 15) | (myexponent & 32767L)));
        return new APInt_(80, cast(ulong[])(words));
    }
    APInt_ convertPPCDoubleDoubleAPFloatToAPInt() {
        ulong[2] words = [0, 0];
        OpStatus_ fs;
        bool losesInfo = false;
        // Convert number to double.  To avoid spurious underflows, we re-
        // normalize against the "double" minExponent first, and only *then*
        // truncate the mantissa.  The result of that second conversion
        // may be inexact, but should never underflow.
        // Declare fltSemantics before APFloat that uses it (and
        // saves pointer to it) to ensure correct destruction order.
        FltSemantics_ extendedSemantics = this.semantics;
        extendedSemantics.minExponent = semIEEEdouble.minExponent;
        IEEEFloat_ extended = new IEEEFloat_(this);
        fs = extended.convert(extendedSemantics, .rmNearestTiesToEven, losesInfo);
        IEEEFloat_ u = new IEEEFloat_(extended);
        fs = u.convert(.semIEEEdouble, .rmNearestTiesToEven, losesInfo);
        words[0] = u.convertDoubleAPFloatToAPInt().getRawData()[0];
        // If conversion was exact or resulted in a special case, we're done;
        // just set the second double to zero.  Otherwise, re-convert back to
        // the extended format and compute the difference.  This now should
        // convert exactly to double.
        if (u.isFiniteNonZero() && losesInfo) {
            fs = u.convert(extendedSemantics, .rmNearestTiesToEven, losesInfo);
            IEEEFloat_ v = new IEEEFloat_(extended);
            v.subtract(u, .rmNearestTiesToEven);
            fs = v.convert(.semIEEEdouble, .rmNearestTiesToEven, losesInfo);
            words[1] = v.convertDoubleAPFloatToAPInt().getRawData()[0];
        }
        else {
            words[1] = 0;
        }
        return new APInt_(128, cast(ulong[])(words));
    }
    APInt_ convertQuadrupleAPFloatToAPInt() {
        ulong myexponent = 0;
        ulong mysignificand = 0;
        ulong mysignificand2 = 0;
        if (this.isFiniteNonZero()) {
            myexponent = this.exponent + 16383; //bias
            mysignificand = this.significandParts()[0];
            mysignificand2 = this.significandParts()[1];
            if (myexponent == 1 && (mysignificand2 & 281474976710656L) == 0) {
                myexponent = 0;
            } // denormal
        }
        else if (this.category == FltCategory_.fcZero) {
            myexponent = 0;
            mysignificand = mysignificand2 = 0;
        }
        else if (this.category == FltCategory_.fcInfinity) {
            myexponent = 32767;
            mysignificand = mysignificand2 = 0;
        }
        else {
            myexponent = 32767;
            mysignificand = this.significandParts()[0];
            mysignificand2 = this.significandParts()[1];
        }
        ulong[2] words = [0, 0];
        words[0] = mysignificand;
        words[1] = (cast(ulong)(((cast(ulong)(this.sign & 1)) << 63) | ((myexponent & 32767) << 48) | (mysignificand2 & 281474976710655L)));
        return new APInt_(128, cast(ulong[])(words));
    }
    OpStatus_ convertToInteger(ulong[] parts, uint width, bool isSigned, RoundingMode_ rounding_mode, ref bool isExact) {
        OpStatus_ fs = this.convertToSignExtendedInteger(parts, width, isSigned, rounding_mode, isExact);
        if (fs == OpStatus_.opInvalidOp) {
            uint bits = 0;
            uint dstPartsCount = .partCountForBits(width);
            assert(dstPartsCount <= parts.length, "Integer too big"c);
            if (this.category == FltCategory_.fcNaN) {
                bits = 0;
            }
            else if (this.sign != 0) {
                bits = isSigned ? 1 : 0;
            }
            else {
                bits = width - (isSigned ? 1 : 0);
            }
            tcSetLeastSignificantBits(parts, dstPartsCount, bits);
            if (this.sign != 0 && isSigned) {
                tcShiftLeft(parts, dstPartsCount, width - 1);
            }
        }
        return fs;
    }
    OpStatus_ convertToSignExtendedInteger(ulong[] parts, uint width, bool isSigned, RoundingMode_ rounding_mode, ref bool isExact) {
        LostFraction_ lost_fraction;
        ulong[] src;
        uint dstPartsCount = 0;
        uint truncatedBits = 0;
        isExact = false;
        /* Handle the three special cases first.  */
        if (this.category == FltCategory_.fcInfinity || this.category == FltCategory_.fcNaN) {
            return OpStatus_.opInvalidOp;
        }
        dstPartsCount = .partCountForBits(width);
        assert(dstPartsCount <= parts.length, "Integer too big"c);
        if (this.category == FltCategory_.fcZero) {
            tcSet(parts, 0, dstPartsCount);
            // Negative zero can't be represented as an int.
            isExact = this.sign == 0;
            return OpStatus_.opOK;
        }
        src = this.significandParts();
        /* Step 1: place our absolute value, with any fraction truncated, in
           the destination.  */
        if (this.exponent < 0) {
            /* Our absolute value is less than one; truncate everything.  */
            tcSet(parts, 0, dstPartsCount);
            /* For exponent -1 the integer bit represents .5, look at that.
               For smaller exponents leftmost truncated bit is 0. */
            truncatedBits = this.semantics.precision - 1u - this.exponent;
        }
        else {
            /* We want the most significant (exponent + 1) bits; the rest are
               truncated.  */
            uint bits = this.exponent + 1u;
            /* Hopelessly large in magnitude?  */
            if (bits > width) {
                return OpStatus_.opInvalidOp;
            }
            if (bits < this.semantics.precision) {
                /* We truncate (semantics.precision - bits) bits.  */
                truncatedBits = this.semantics.precision - bits;
                tcExtract(parts, dstPartsCount, src, bits, truncatedBits);
            }
            else {
                /* We want at least as many bits as are available.  */
                tcExtract(parts, dstPartsCount, src, this.semantics.precision, 0);
                tcShiftLeft(parts, dstPartsCount, bits - this.semantics.precision);
                truncatedBits = 0;
            }
        }
        /* Step 2: work out any lost fraction, and increment the absolute
           value 如果 we would round away from zero.  */
        if (truncatedBits != 0) {
            lost_fraction = .lostFractionThroughTruncation(src, this.partCount(), truncatedBits);
            if (lost_fraction != LostFraction_.lfExactlyZero && this.roundAwayFromZero(rounding_mode, lost_fraction, truncatedBits)) {
                if (tcIncrement(parts, dstPartsCount) != 0) {
                    return OpStatus_.opInvalidOp;
                } /* Overflow.  */
            }
        }
        else {
            lost_fraction = LostFraction_.lfExactlyZero;
        }
        /* Step 3: check 如果 we fit in the destination.  */
        uint omsb = tcMSB(parts, dstPartsCount) + 1;
        if (this.sign != 0) {
            if (!isSigned) {
                /* Negative numbers cannot be represented as unsigned.  */
                if (omsb != 0) {
                    return OpStatus_.opInvalidOp;
                }
            }
            else {
                /* It takes omsb bits to represent the unsigned integer value.
                   We lose a bit for the sign, but care is needed as the
                   maximally negative integer is a special case.  */
                if (omsb == width && tcLSB(parts, dstPartsCount) + 1 != omsb) {
                    return OpStatus_.opInvalidOp;
                }
                /* This case can happen because of rounding.  */
                if (omsb > width) {
                    return OpStatus_.opInvalidOp;
                }
            }
            tcNegate(parts, dstPartsCount);
        }
        else {
            if (omsb >= width + (!isSigned ? 1 : 0)) {
                return OpStatus_.opInvalidOp;
            }
        }
        if (lost_fraction == LostFraction_.lfExactlyZero) {
            isExact = true;
            return OpStatus_.opOK;
        }
        else {
            return OpStatus_.opInexact;
        }
    }
    uint partCount() {
        return .partCountForBits(this.semantics.precision + 1);
    }
    int exponentZero() {
        return this.semantics.minExponent - 1;
    }
    int exponentInf() {
        return this.semantics.maxExponent + 1;
    }
    void makeInf(bool Negative) {
        this.category = FltCategory_.fcInfinity;
        this.sign = Negative ? 1 : 0;
        this.exponent = this.exponentInf();
        tcSet(this.significand, 0, this.partCount());
    }
    void makeZero(bool Negative) {
        this.category = FltCategory_.fcInfinity;
        this.sign = Negative ? 1 : 0;
        this.exponent = this.exponentZero();
        tcSet(this.significand, 0, this.partCount());
    }
    void makeQuiet() {
        tcSetBit(this.significand, this.semantics.precision - 2);
    }
    ulong[] significandParts() {
        return this.significand;
    }
    bool isNegative() { return this.sign == 1; }
    bool isNormal() { return !this.isDenormal() && this.isFiniteNonZero(); }
    bool isDenormal() {
        return this.isFiniteNonZero() && (this.exponent == this.semantics.minExponent) && (tcExtractBit(this.significand, this.semantics.precision - 1) == 0);
    }
    bool isFinite() { return !this.isNaN() && !this.isInfinity(); }
    bool isZero() { return this.category == FltCategory_.fcZero; }
    bool isInfinity() { return this.category == FltCategory_.fcInfinity; }
    bool isNaN() { return this.category == FltCategory_.fcNaN; }
    FltCategory_ getCategory() { return this.category; }
    FltSemantics_ getSemantics() { return this.semantics; }
    bool isNonZero() { return this.category != FltCategory_.fcZero; }
    bool isFiniteNonZero() { return this.isFinite() && !this.isZero(); }
    bool isPosZero() { return this.isZero() && !this.isNegative(); }
    bool isNegZero() { return this.isZero() && this.isNegative(); }
    bool isSignaling() {
        if (!this.isNaN()) {
            return false;
        }
        // IEEE-754R 2008 6.2.1: A signaling NaN bit string should be encoded with the
        // first bit of the trailing significand being 0.
        return !tcExtractBit(this.significand, this.semantics.precision - 2);
    }
    void assign(IEEEFloat_ rhs) {
        this.sign = rhs.sign;
        this.category = rhs.category;
        this.exponent = rhs.exponent;
        if (this.isFiniteNonZero() || this.category == FltCategory_.fcNaN) {
            this.copySignificand(rhs);
        }
    }
    void copySignificand(IEEEFloat_ rhs) {
        tcAssign(this.significand, rhs.significand, this.partCount());
    }
    bool isSmallest() {
        // The smallest number by magnitude in our format will be the smallest
        // denormal, i.e. the floating point number with exponent being minimum
        // exponent and significand bitwise equal to 1 (i.e. with MSB equal to 0).
        return this.isFiniteNonZero() && this.exponent == this.semantics.minExponent && this.significandMSB() == 0;
    }
    uint significandMSB() {
        return tcMSB(this.significand, this.partCount());
    }
    bool isSignificandAllOnes() {
        // Test 如果 the significand excluding the integral bit is all ones. This allows
        // us to test 循环 binade boundaries.
        ulong[] Parts = this.significandParts();
        uint PartCount = .partCountForBits(this.semantics.precision);
        {
            for (uint i = 0; i < PartCount - 1; ++i) {
                if ((~Parts[i]) != 0) {
                    return false;
                }
            }
        }
        // Set the unused high bits to all ones when we compare.
        uint NumHighBits = (cast(uint)(PartCount * .integerPartWidth - this.semantics.precision + 1));
        ulong HighBitFill = ~(cast(IntegerPart_)(0)) << (.integerPartWidth - NumHighBits);
        if ((~(Parts[PartCount - 1] | HighBitFill)) != 0) {
            return false;
        }
        return true;
    }
    bool isSignificandAllZeros() {
        // Test 如果 the significand excluding the integral bit is all zeros. This
        // allows us to test 循环 binade boundaries.
        ulong[] Parts = this.significandParts();
        uint PartCount = .partCountForBits(this.semantics.precision);
        {
            for (uint i = 0; i < PartCount - 1; ++i) {
                if (Parts[i] != 0) {
                    return false;
                }
            }
        }
        // Compute how many bits are used in the final word.
        uint NumHighBits = (cast(uint)(PartCount * .integerPartWidth - this.semantics.precision + 1));
        ulong HighBitMask = ~(cast(IntegerPart_)(0)) >> NumHighBits;
        if ((Parts[PartCount - 1] & HighBitMask) != 0) {
            return false;
        }
        return true;
    }
    bool isLargest() {
        // The largest number by magnitude in our format will be the floating point
        // number with maximum exponent and with significand that is all ones.
        return this.isFiniteNonZero() && this.exponent == this.semantics.maxExponent && this.isSignificandAllOnes();
    }
    bool isInteger() {
        // This could be made more efficient; I'm going 循环 obviously correct.
        if (!this.isFinite()) {
            return false;
        }
        IEEEFloat_ truncated = this;
        truncated.roundToIntegral(.rmTowardZero);
        return this.compare(truncated) == CmpResult_.cmpEqual;
    }
    bool bitwiseIsEqual(IEEEFloat_ rhs) {
        if (this == rhs) {
            return true;
        }
        if (this.semantics != rhs.semantics || this.category != rhs.category || this.sign != rhs.sign) {
            return false;
        }
        if (this.category == FltCategory_.fcZero || this.category == FltCategory_.fcInfinity) {
            return true;
        }
        if (this.isFiniteNonZero() && this.exponent != rhs.exponent) {
            return false;
        }
        return rangeEquals!(ulong)(this.significandParts(), rhs.significandParts(), 0, 0);
    }
    void zeroSignificand() {
        tcSet(this.significand, 0, this.partCount());
    }
    IEEEFloat_ getIEEE() {
        return this;
    }
    OpStatus_ roundToIntegral(RoundingMode_ rounding_mode) {
        OpStatus_ fs;
        if (this.isInfinity()) {
            // [IEEE Std 754-2008 6.1]:
            // The behavior of infinity in floating-point arithmetic is derived from the
            // limiting 若是s of real arithmetic with operands of arbitrarily
            // large magnitude, when such a limit exists.
            // ...
            // Operations on infinite operands are usually exact and therefore signal no
            // exceptions ...
            return OpStatus_.opOK;
        }
        if (this.isNaN()) {
            if (this.isSignaling()) {
                // [IEEE Std 754-2008 6.2]:
                // Under default exception handling, any operation signaling an invalid
                // operation exception and for which a floating-point result is to be
                // delivered shall deliver a quiet NaN.
                this.makeQuiet();
                // [IEEE Std 754-2008 6.2]:
                // Signaling NaNs shall be reserved operands that, under default exception
                // handling, signal the invalid operation exception(see 7.2) for every
                // general-computational and signaling-computational operation except for
                // the conversions described in 5.12.
                return OpStatus_.opInvalidOp;
            }
            else {
                // [IEEE Std 754-2008 6.2]:
                // For an operation with quiet NaN inputs, other than maximum and minimum
                // operations, 如果 a floating-point result is to be delivered the result
                // shall be a quiet NaN which should be one of the input NaNs.
                // ...
                // Every general-computational and quiet-computational operation involving
                // one or more input NaNs, none of them signaling, shall signal no
                // exception, except fusedMultiplyAdd might signal the invalid operation
                // exception(see 7.2).
                return OpStatus_.opOK;
            }
        }
        if (this.isZero()) {
            // [IEEE Std 754-2008 6.3]:
            // ... the sign of the result of conversions, the quantize operation, the
            // roundToIntegral operations, and the roundToIntegralExact(see 5.3.1) is
            // the sign of the first or only operand.
            return OpStatus_.opOK;
        }
        // If the exponent is large enough, we know that this value is already
        // integral, and the arithmetic below would potentially cause it to saturate
        // to +/-Inf.  Bail out early instead.
        if (this.exponent + 1 >= (cast(int)(.semanticsPrecision(this.semantics)))) {
            return OpStatus_.opOK;
        }
        // The algorithm here is quite simple: we add 2^(p-1), where p is the
        // precision of our format, and then subtract it back off again.  The choice
        // of rounding modes for the addition/subtraction determines the rounding mode
        // for our integral rounding as well.
        // NOTE: When the input value is negative, we do subtraction followed by
        // addition instead.
        APInt_ IntegerConstant = new APInt_((cast(uint)(NextPowerOf2(.semanticsPrecision(this.semantics)))), 1, false);
        IntegerConstant.Op左移等(.semanticsPrecision(this.semantics) - 1);
        IEEEFloat_ MagicConstant = new IEEEFloat_(this.semantics);
        fs = MagicConstant.convertFromAPInt(IntegerConstant, false, .rmNearestTiesToEven);
        MagicConstant.sign = this.sign;
        // Preserve the input sign so that we can handle the 若是 of zero result
        // correctly.
        bool inputSign = this.isNegative();
        fs = this.add(MagicConstant, rounding_mode);
        // Current value and 'MagicConstant' are both integers, so the result of the
        // subtraction is always exact according to Sterbenz' lemma.
        this.subtract(MagicConstant, rounding_mode);
        // Restore the input sign.
        if (inputSign != this.isNegative()) {
            this.changeSign();
        }
        return fs;
    }
    void changeSign() {
        /* Look mummy, this one's easy.  */
        this.sign = this.sign != 0 ? 0 : 1;
    }
    OpStatus_ convertFromAPInt(APInt_ Val, bool isSigned, RoundingMode_ rounding_mode) {
        uint partCounts = Val.getNumWords();
        APInt_ api = Val;
        this.sign = 0;
        if (isSigned && api.isNegative()) {
            this.sign = 1;
            api = Op负(api);
        }
        return this.convertFromUnsignedParts(api.getRawData(), partCounts, rounding_mode);
    }
    OpStatus_ convertFromUnsignedParts(ulong[] src, uint srcCount, RoundingMode_ rounding_mode) {
        this.category = FltCategory_.fcNormal;
        uint omsb = tcMSB(src, srcCount) + 1;
        uint precision = this.semantics.precision;
        uint dstCount = this.partCount();
        LostFraction_ lost_fraction;
        /* We want the most significant PRECISION bits of SRC.  There may not
           be that many; extract what we can.  */
        if (precision <= omsb) {
            this.exponent = omsb - 1;
            lost_fraction = .lostFractionThroughTruncation(src, srcCount, omsb - precision);
            tcExtract(this.significand, dstCount, src, precision, omsb - precision);
        }
        else {
            this.exponent = precision - 1;
            lost_fraction = LostFraction_.lfExactlyZero;
            tcExtract(this.significand, dstCount, src, omsb, 0);
        }
        return this.normalize(rounding_mode, lost_fraction);
    }
    OpStatus_ normalize(RoundingMode_ rounding_mode, LostFraction_ lost_fraction) {
        uint omsb = 0; /* One, not zero, based MSB.  */
        int exponentChange = 0;
        if (!this.isFiniteNonZero()) {
            return OpStatus_.opOK;
        }
        /* Before rounding normalize the exponent of fcNormal numbers.  */
        omsb = this.significandMSB() + 1;
        if (omsb != 0) {
            /* OMSB is numbered from 1.  We want to place it in the integer
            bit numbered PRECISION 如果 possible, with a compensating change in
            the exponent.  */
            exponentChange = omsb - this.semantics.precision;
            /* 如果 the resulting exponent is too high, overflow according to
            the rounding mode.  */
            if (this.exponent + exponentChange > this.semantics.maxExponent) {
                return this.handleOverflow(rounding_mode);
            }
            /* Subnormal numbers have exponent minExponent, and their MSB
            is forced based on that.  */
            if (this.exponent + exponentChange < this.semantics.minExponent) {
                exponentChange = this.semantics.minExponent - this.exponent;
            }
            /* Sh如果ting left is easy as we don't lose precision.  */
            if (exponentChange < 0) {
                this.shiftSignificandLeft(-exponentChange);
                return OpStatus_.opOK;
            }
            if (exponentChange > 0) {
                LostFraction_ lf;
                /* Sh如果t right and capture any new lost fraction.  */
                lf = this.shiftSignificandRight(exponentChange);
                lost_fraction = .combineLostFractions(lf, lost_fraction);
                /* Keep OMSB up-to-date.  */
                if (omsb > (cast(uint)(exponentChange))) {
                    omsb -= exponentChange;
                }
                else {
                    omsb = 0;
                }
            }
        }
        /* Now round the number according to rounding_mode given the lost
        fraction.  */
        /* As spec如果ied in IEEE 754, since we do not trap we do not report
        underflow for exact results.  */
        if (lost_fraction == LostFraction_.lfExactlyZero) {
            /* Canonicalize zeroes.  */
            if (omsb == 0) {
                this.category = FltCategory_.fcZero;
            }
            return OpStatus_.opOK;
        }
        /* Increment the sign如果icand 如果 we're rounding away from zero.  */
        if (this.roundAwayFromZero(rounding_mode, lost_fraction, 0)) {
            if (omsb == 0) {
                this.exponent = this.semantics.minExponent;
            }
            this.incrementSignificand();
            omsb = this.significandMSB() + 1;
            /* Did the sign如果icand increment overflow?  */
            if (omsb == (cast(uint)(this.semantics.precision + 1))) {
                /* Renormalize by incrementing the exponent and sh如果ting our
                sign如果icand right one.  However 如果 we already have the
                maximum exponent we overflow to infinity.  */
                if (this.exponent == this.semantics.maxExponent) {
                    this.category = FltCategory_.fcInfinity;
                    return (cast(OpStatus_)(OpStatus_.opOverflow | OpStatus_.opInexact));
                }
                this.shiftSignificandRight(1);
                return OpStatus_.opInexact;
            }
        }
        /* The normal 若是 - we were and are not denormal, and any
        sign如果icand increment above didn't overflow.  */
        if (omsb == this.semantics.precision) {
            return OpStatus_.opInexact;
        }
        /* Canonicalize zeroes.  */
        if (omsb == 0) {
            this.category = FltCategory_.fcZero;
        }
        /* The fcZero 若是 is a denormal that underflowed to zero.  */
        return (cast(OpStatus_)(OpStatus_.opUnderflow | OpStatus_.opInexact));
    }
    OpStatus_ handleOverflow(RoundingMode_ rounding_mode) {
        /* Infinity?  */
        if (rounding_mode == .rmNearestTiesToEven || rounding_mode == .rmNearestTiesToAway || (rounding_mode == .rmTowardPositive && this.sign == 0) || (rounding_mode == .rmTowardNegative && this.sign == 1)) {
            this.category = FltCategory_.fcInfinity;
            return (cast(OpStatus_)(OpStatus_.opOverflow | OpStatus_.opInexact));
        }
        /* Otherwise we become the largest finite number.  */
        this.category = FltCategory_.fcNormal;
        this.exponent = this.semantics.maxExponent;
        tcSetLeastSignificantBits(this.significand, this.partCount(), this.semantics.precision);
        return OpStatus_.opInexact;
    }
    void shiftSignificandLeft(uint bits) {
        if (bits != 0) {
            uint partsCount = this.partCount();
            tcShiftLeft(this.significand, partsCount, bits);
            this.exponent -= bits;
            tcIsZero(this.significand, partsCount);
        }
    }
    LostFraction_ shiftSignificandRight(uint bits) {
        this.exponent += bits;
        return .shiftRight(this.significand, this.partCount(), bits);
    }
    bool roundAwayFromZero(RoundingMode_ rounding_mode, LostFraction_ lost_fraction, uint bit) {
        switch (rounding_mode) {
            case RoundingMode_.NearestTiesToAway: {
                return lost_fraction == LostFraction_.lfExactlyHalf || lost_fraction == LostFraction_.lfMoreThanHalf;
            }
            case RoundingMode_.NearestTiesToEven: {
                if (lost_fraction == LostFraction_.lfMoreThanHalf) {
                    return true;
                }
                /* Our zeroes don't have a significand to test.  */
                if (lost_fraction == LostFraction_.lfExactlyHalf && this.category != FltCategory_.fcZero) {
                    return tcExtractBit(this.significand, bit);
                }
                return false;
            }
            case RoundingMode_.TowardZero: {
                return false;
            }
            case RoundingMode_.TowardPositive: {
                return this.sign == 0;
            }
            case RoundingMode_.TowardNegative: {
                return this.sign != 0;
            }
            default: {
                break;
            }
        }
        return false;
    }
    void incrementSignificand() {
        tcIncrement(this.significand, this.partCount());
    }
    OpStatus_ add(IEEEFloat_ rhs, RoundingMode_ rounding_mode) {
        return this.addOrSubtract(rhs, rounding_mode, false);
    }
    OpStatus_ subtract(IEEEFloat_ rhs, RoundingMode_ rounding_mode) {
        return this.addOrSubtract(rhs, rounding_mode, true);
    }
    OpStatus_ addOrSubtract(IEEEFloat_ rhs, RoundingMode_ roundingmode, bool subtract) {
        OpStatus_ fs = this.addOrSubtractSpecials(rhs, subtract);
        /* This 返回 code means it was not a simple case.  */
        if (fs == OpStatus_.opDivByZero) {
            LostFraction_ lost_fraction = this.addOrSubtractSignificand(rhs, subtract);
            fs = this.normalize(roundingmode, lost_fraction);
        }
        /* If two numbers add (exactly) to zero, IEEE 754 decrees it is a
        positive zero unless rounding to minus infinity, except that
        adding two like-signed zeroes gives that zero.  */
        if (this.category == FltCategory_.fcZero) {
            if (rhs.category != FltCategory_.fcZero || (this.sign == rhs.sign) == subtract) {
                this.sign = (roundingmode == RoundingMode_.TowardNegative) ? 1 : 0;
            }
        }
        return fs;
    }
    OpStatus_ fusedMultiplyAdd(IEEEFloat_ multiplicand, IEEEFloat_ addend, RoundingMode_ rounding_mode) {
        OpStatus_ fs = OpStatus_.opOK;
        /* Post-multiplication sign, before addition.  */
        this.sign ^= multiplicand.sign;
        /* If and only 如果 all arguments are normal do we need to do an
        extended-precision calculation.  */
        if (this.isFiniteNonZero() && multiplicand.isFiniteNonZero() && addend.isFinite()) {
            LostFraction_ lost_fraction = this.multiplySignificand(multiplicand, addend);
            fs = this.normalize(rounding_mode, lost_fraction);
            if (lost_fraction != LostFraction_.lfExactlyZero) {
                fs = fs | OpStatus_.opInexact;
            }
            /* If two numbers add (exactly) to zero, IEEE 754 decrees it is a
            positive zero unless rounding to minus infinity, except that
            adding two like-signed zeroes gives that zero.  */
            if (this.category == FltCategory_.fcZero && (fs & OpStatus_.opUnderflow) == 0 && this.sign != addend.sign) {
                this.sign = (rounding_mode == .rmTowardNegative) ? 1 : 0;
            }
        }
        else {
            fs = this.multiplySpecials(multiplicand);
            /* FS can only be opOK or opInvalidOp.  There is no more work
            to do in the latter case.  The IEEE-754R standard says it is
            implementation-defined in this case whether, 如果 ADDEND is a
            quiet NaN, we raise invalid op; this implementation does so.
            
            If we need to do the addition we can do so with normal
            precision.  */
            if (fs == OpStatus_.opOK) {
                fs = this.addOrSubtract(addend, rounding_mode, false);
            }
        }
        return fs;
    }
    OpStatus_ multiplySpecials(IEEEFloat_ rhs) {
        ulong cat = .PackCategoriesIntoKey(this.category, rhs.category);
        if (cat == .PackCategoriesIntoKey(FltCategory_.fcZero, FltCategory_.fcNaN) || cat == .PackCategoriesIntoKey(FltCategory_.fcNormal, FltCategory_.fcNaN) || cat == .PackCategoriesIntoKey(FltCategory_.fcInfinity, FltCategory_.fcNaN) || cat == .PackCategoriesIntoKey(FltCategory_.fcNaN, FltCategory_.fcZero) || cat == .PackCategoriesIntoKey(FltCategory_.fcNaN, FltCategory_.fcNormal) || cat == .PackCategoriesIntoKey(FltCategory_.fcNaN, FltCategory_.fcInfinity) || cat == .PackCategoriesIntoKey(FltCategory_.fcNaN, FltCategory_.fcNaN)) {
            if (cat == .PackCategoriesIntoKey(FltCategory_.fcZero, FltCategory_.fcNaN) || cat == .PackCategoriesIntoKey(FltCategory_.fcNormal, FltCategory_.fcNaN) || cat == .PackCategoriesIntoKey(FltCategory_.fcInfinity, FltCategory_.fcNaN)) {
                this.assign(rhs);
                this.sign = 0;
            }
            this.sign ^= rhs.sign;
            if (this.isSignaling()) {
                this.makeQuiet();
                return OpStatus_.opInvalidOp;
            }
            return rhs.isSignaling() ? OpStatus_.opInvalidOp : OpStatus_.opOK;
        }
        if (cat == .PackCategoriesIntoKey(FltCategory_.fcNormal, FltCategory_.fcInfinity) || cat == .PackCategoriesIntoKey(FltCategory_.fcInfinity, FltCategory_.fcNormal) || cat == .PackCategoriesIntoKey(FltCategory_.fcInfinity, FltCategory_.fcInfinity)) {
            this.category = FltCategory_.fcInfinity;
            return OpStatus_.opOK;
        }
        if (cat == .PackCategoriesIntoKey(FltCategory_.fcZero, FltCategory_.fcNormal) || cat == .PackCategoriesIntoKey(FltCategory_.fcNormal, FltCategory_.fcZero) || cat == .PackCategoriesIntoKey(FltCategory_.fcZero, FltCategory_.fcZero)) {
            this.category = FltCategory_.fcZero;
            return OpStatus_.opOK;
        }
        if (cat == .PackCategoriesIntoKey(FltCategory_.fcZero, FltCategory_.fcInfinity) || cat == .PackCategoriesIntoKey(FltCategory_.fcInfinity, FltCategory_.fcZero)) {
            this.makeNaN(false, false);
            return OpStatus_.opInvalidOp;
        }
        if (cat == .PackCategoriesIntoKey(FltCategory_.fcNormal, FltCategory_.fcNormal)) {
            return OpStatus_.opOK;
        }
        assert(false, "不可及"c);
        return OpStatus_.opOK;
    }
    OpStatus_ divide(IEEEFloat_ rhs, RoundingMode_ rounding_mode) {
        this.sign ^= rhs.sign;
        OpStatus_ fs = this.divideSpecials(rhs);
        if (this.isFiniteNonZero()) {
            LostFraction_ lost_fraction = this.divideSignificand(rhs);
            fs = this.normalize(rounding_mode, lost_fraction);
            if (lost_fraction != LostFraction_.lfExactlyZero) {
                fs = (fs | OpStatus_.opInexact);
            }
        }
        return fs;
    }
    OpStatus_ mod(IEEEFloat_ rhs) {
        uint origSign = this.sign;
        OpStatus_ fs = this.modSpecials(rhs);
        while(this.isFiniteNonZero() && rhs.isFiniteNonZero() && this.compareAbsoluteValue(rhs) != CmpResult_.cmpLessThan) {
            IEEEFloat_ V = .scalbn(rhs, .ilogb(this) - .ilogb(rhs), .rmNearestTiesToEven);
            if (this.compareAbsoluteValue(rhs) == CmpResult_.cmpLessThan) {
                V = .scalbn(V, -1, .rmNearestTiesToEven);
            }
            V.sign = this.sign;
            fs = this.subtract(V, .rmNearestTiesToEven);
        }
        if (this.isZero()) {
            this.sign = origSign;
        }
        return fs;
    }
    OpStatus_ modSpecials(IEEEFloat_ rhs) {
        ulong cat = .PackCategoriesIntoKey(this.category, rhs.category);
        if (cat == .PackCategoriesIntoKey(FltCategory_.fcZero, FltCategory_.fcNaN) || cat == .PackCategoriesIntoKey(FltCategory_.fcNormal, FltCategory_.fcNaN) || cat == .PackCategoriesIntoKey(FltCategory_.fcInfinity, FltCategory_.fcNaN) || cat == .PackCategoriesIntoKey(FltCategory_.fcNaN, FltCategory_.fcZero) || cat == .PackCategoriesIntoKey(FltCategory_.fcNaN, FltCategory_.fcNormal) || cat == .PackCategoriesIntoKey(FltCategory_.fcNaN, FltCategory_.fcInfinity) || cat == .PackCategoriesIntoKey(FltCategory_.fcNaN, FltCategory_.fcNaN)) {
            if (cat == .PackCategoriesIntoKey(FltCategory_.fcZero, FltCategory_.fcNaN) || cat == .PackCategoriesIntoKey(FltCategory_.fcNormal, FltCategory_.fcNaN) || cat == .PackCategoriesIntoKey(FltCategory_.fcInfinity, FltCategory_.fcNaN)) {
                this.assign(rhs);
            }
            if (this.isSignaling()) {
                this.makeQuiet();
                return OpStatus_.opInvalidOp;
            }
            return rhs.isSignaling() ? OpStatus_.opInvalidOp : OpStatus_.opOK;
        }
        if (cat == .PackCategoriesIntoKey(FltCategory_.fcZero, FltCategory_.fcInfinity) || cat == .PackCategoriesIntoKey(FltCategory_.fcZero, FltCategory_.fcNormal) || cat == .PackCategoriesIntoKey(FltCategory_.fcNormal, FltCategory_.fcInfinity)) {
            return OpStatus_.opOK;
        }
        if (cat == .PackCategoriesIntoKey(FltCategory_.fcNormal, FltCategory_.fcZero) || cat == .PackCategoriesIntoKey(FltCategory_.fcInfinity, FltCategory_.fcZero) || cat == .PackCategoriesIntoKey(FltCategory_.fcInfinity, FltCategory_.fcNormal) || cat == .PackCategoriesIntoKey(FltCategory_.fcInfinity, FltCategory_.fcInfinity) || cat == .PackCategoriesIntoKey(FltCategory_.fcZero, FltCategory_.fcZero)) {
            this.makeNaN(false, false);
            return OpStatus_.opInvalidOp;
        }
        if (cat == .PackCategoriesIntoKey(FltCategory_.fcNormal, FltCategory_.fcNormal)) {
            return OpStatus_.opOK;
        }
        assert(false, "不可及"c);
        return OpStatus_.opOK;
    }
    OpStatus_ divideSpecials(IEEEFloat_ rhs) {
        ulong cat = .PackCategoriesIntoKey(this.category, rhs.category);
        if (cat == .PackCategoriesIntoKey(FltCategory_.fcZero, FltCategory_.fcNaN) || cat == .PackCategoriesIntoKey(FltCategory_.fcNormal, FltCategory_.fcNaN) || cat == .PackCategoriesIntoKey(FltCategory_.fcInfinity, FltCategory_.fcNaN) || cat == .PackCategoriesIntoKey(FltCategory_.fcNaN, FltCategory_.fcZero) || cat == .PackCategoriesIntoKey(FltCategory_.fcNaN, FltCategory_.fcNormal) || cat == .PackCategoriesIntoKey(FltCategory_.fcNaN, FltCategory_.fcInfinity) || cat == .PackCategoriesIntoKey(FltCategory_.fcNaN, FltCategory_.fcNaN)) {
            if (cat == .PackCategoriesIntoKey(FltCategory_.fcZero, FltCategory_.fcNaN) || cat == .PackCategoriesIntoKey(FltCategory_.fcNormal, FltCategory_.fcNaN) || cat == .PackCategoriesIntoKey(FltCategory_.fcInfinity, FltCategory_.fcNaN)) {
                this.assign(rhs);
                this.sign = 0;
            }
            this.sign ^= rhs.sign;
            if (this.isSignaling()) {
                this.makeQuiet();
                return OpStatus_.opInvalidOp;
            }
            return rhs.isSignaling() ? OpStatus_.opInvalidOp : OpStatus_.opOK;
        }
        if (cat == .PackCategoriesIntoKey(FltCategory_.fcInfinity, FltCategory_.fcZero) || cat == .PackCategoriesIntoKey(FltCategory_.fcInfinity, FltCategory_.fcNormal) || cat == .PackCategoriesIntoKey(FltCategory_.fcZero, FltCategory_.fcInfinity) || cat == .PackCategoriesIntoKey(FltCategory_.fcZero, FltCategory_.fcNormal)) {
            return OpStatus_.opOK;
        }
        if (cat == .PackCategoriesIntoKey(FltCategory_.fcNormal, FltCategory_.fcInfinity)) {
            this.category = FltCategory_.fcZero;
            return OpStatus_.opOK;
        }
        if (cat == .PackCategoriesIntoKey(FltCategory_.fcNormal, FltCategory_.fcZero)) {
            this.category = FltCategory_.fcInfinity;
            return OpStatus_.opDivByZero;
        }
        if (cat == .PackCategoriesIntoKey(FltCategory_.fcInfinity, FltCategory_.fcInfinity) || cat == .PackCategoriesIntoKey(FltCategory_.fcZero, FltCategory_.fcZero)) {
            this.makeNaN(false, false);
            return OpStatus_.opInvalidOp;
        }
        if (cat == .PackCategoriesIntoKey(FltCategory_.fcNormal, FltCategory_.fcNormal)) {
            return OpStatus_.opOK;
        }
        assert(false, "不可及"c);
        return OpStatus_.opOK;
    }
    OpStatus_ addOrSubtractSpecials(IEEEFloat_ rhs, bool subtract) {
        ulong cat = .PackCategoriesIntoKey(this.category, rhs.category);
        if (cat == .PackCategoriesIntoKey(FltCategory_.fcZero, FltCategory_.fcNaN) || cat == .PackCategoriesIntoKey(FltCategory_.fcNormal, FltCategory_.fcNaN) || cat == .PackCategoriesIntoKey(FltCategory_.fcInfinity, FltCategory_.fcNaN)) {
            this.assign(rhs);
        }
        if (cat == .PackCategoriesIntoKey(FltCategory_.fcZero, FltCategory_.fcNaN) || cat == .PackCategoriesIntoKey(FltCategory_.fcNormal, FltCategory_.fcNaN) || cat == .PackCategoriesIntoKey(FltCategory_.fcInfinity, FltCategory_.fcNaN) || cat == .PackCategoriesIntoKey(FltCategory_.fcNaN, FltCategory_.fcZero) || cat == .PackCategoriesIntoKey(FltCategory_.fcNaN, FltCategory_.fcNormal) || cat == .PackCategoriesIntoKey(FltCategory_.fcNaN, FltCategory_.fcInfinity) || cat == .PackCategoriesIntoKey(FltCategory_.fcNaN, FltCategory_.fcNaN)) {
            if (this.isSignaling()) {
                this.makeQuiet();
                return OpStatus_.opInvalidOp;
            }
            return rhs.isSignaling() ? OpStatus_.opInvalidOp : OpStatus_.opOK;
        }
        else if (cat == .PackCategoriesIntoKey(FltCategory_.fcNormal, FltCategory_.fcZero) || cat == .PackCategoriesIntoKey(FltCategory_.fcInfinity, FltCategory_.fcNormal) || cat == .PackCategoriesIntoKey(FltCategory_.fcInfinity, FltCategory_.fcZero)) {
            return OpStatus_.opOK;
        }
        else if (cat == .PackCategoriesIntoKey(FltCategory_.fcNormal, FltCategory_.fcInfinity) || cat == .PackCategoriesIntoKey(FltCategory_.fcZero, FltCategory_.fcInfinity)) {
            this.category = FltCategory_.fcInfinity;
            this.sign = rhs.sign ^ (subtract ? 1 : 0);
            return OpStatus_.opOK;
        }
        else if (cat == .PackCategoriesIntoKey(FltCategory_.fcZero, FltCategory_.fcNormal)) {
            this.assign(rhs);
            this.sign = rhs.sign ^ (subtract ? 1 : 0);
            return OpStatus_.opOK;
        }
        else if (cat == .PackCategoriesIntoKey(FltCategory_.fcZero, FltCategory_.fcZero)) {
            return OpStatus_.opOK;
        }
        else if (cat == .PackCategoriesIntoKey(FltCategory_.fcInfinity, FltCategory_.fcInfinity)) {
            if (((this.sign ^ rhs.sign) != 0) != subtract) {
                this.makeNaN(false, false);
                return OpStatus_.opInvalidOp;
            }
            return OpStatus_.opOK;
        }
        else if (cat == .PackCategoriesIntoKey(FltCategory_.fcNormal, FltCategory_.fcNormal)) {
            return OpStatus_.opDivByZero;
        }
        return OpStatus_.opOK;
    }
    LostFraction_ addOrSubtractSignificand(IEEEFloat_ rhs, bool subtract) {
        ulong carry;
        LostFraction_ lost_fraction;
        int bits;
        /* Determine 如果 the operation on the absolute values is effectively
        an addition or subtraction.  */
        int n = subtract ? 1 : 0;
        uint tem = n ^ (this.sign ^ rhs.sign);
        subtract = tem != 0 ? true : false;
        /* Are we bigger exponent-wise than the RHS?  */
        bits = this.exponent - rhs.exponent;
        /* Subtraction is more subtle than one might naively expect.  */
        if (subtract) {
            IEEEFloat_ temp_rhs = rhs;
            if (bits == 0) {
                lost_fraction = LostFraction_.lfExactlyZero;
            }
            else if (bits > 0) {
                lost_fraction = temp_rhs.shiftSignificandRight(bits - 1);
                this.shiftSignificandLeft(1);
            }
            else {
                lost_fraction = this.shiftSignificandRight(-bits - 1);
                temp_rhs.shiftSignificandLeft(1);
            }
            // Should we reverse the subtraction.
            if (this.compareAbsoluteValue(temp_rhs) == CmpResult_.cmpLessThan) {
                carry = temp_rhs.subtractSignificand(this, lost_fraction != LostFraction_.lfExactlyZero ? 1 : 0);
                this.copySignificand(temp_rhs);
                this.sign = this.sign != 0 ? 0 : 1;
            }
            else {
                carry = this.subtractSignificand(temp_rhs, lost_fraction != LostFraction_.lfExactlyZero ? 1 : 0);
            }
            /* Invert the lost fraction - it was on the RHS and
            subtracted.  */
            if (lost_fraction == LostFraction_.lfLessThanHalf) {
                lost_fraction = LostFraction_.lfMoreThanHalf;
            }
            else if (lost_fraction == LostFraction_.lfMoreThanHalf) {
                lost_fraction = LostFraction_.lfLessThanHalf;
            }
        }
        else {
            if (bits > 0) {
                IEEEFloat_ temp_rhs = rhs;
                lost_fraction = temp_rhs.shiftSignificandRight(bits);
                carry = this.addSignificand(temp_rhs);
            }
            else {
                lost_fraction = this.shiftSignificandRight(-bits);
                carry = this.addSignificand(rhs);
            }
        }
        return lost_fraction;
    }
    CmpResult_ compare(IEEEFloat_ rhs) {
        CmpResult_ result = CmpResult_.cmpEqual;
        ulong pac = .PackCategoriesIntoKey(this.category, rhs.category);
        if (pac == .PackCategoriesIntoKey(FltCategory_.fcNaN, FltCategory_.fcZero) || pac == .PackCategoriesIntoKey(FltCategory_.fcNaN, FltCategory_.fcNormal) || pac == .PackCategoriesIntoKey(FltCategory_.fcNaN, FltCategory_.fcInfinity) || pac == .PackCategoriesIntoKey(FltCategory_.fcNaN, FltCategory_.fcNaN) || pac == .PackCategoriesIntoKey(FltCategory_.fcZero, FltCategory_.fcNaN) || pac == .PackCategoriesIntoKey(FltCategory_.fcNormal, FltCategory_.fcNaN) || pac == .PackCategoriesIntoKey(FltCategory_.fcInfinity, FltCategory_.fcNaN)) {
            return CmpResult_.cmpUnordered;
        }
        else if (pac == .PackCategoriesIntoKey(FltCategory_.fcInfinity, FltCategory_.fcNormal) || pac == .PackCategoriesIntoKey(FltCategory_.fcInfinity, FltCategory_.fcZero) || pac == .PackCategoriesIntoKey(FltCategory_.fcNormal, FltCategory_.fcZero)) {
            if (this.sign != 0) {
                return CmpResult_.cmpLessThan;
            }
            else {
                return CmpResult_.cmpGreaterThan;
            }
        }
        else if (pac == .PackCategoriesIntoKey(FltCategory_.fcNormal, FltCategory_.fcInfinity) || pac == .PackCategoriesIntoKey(FltCategory_.fcZero, FltCategory_.fcInfinity) || pac == .PackCategoriesIntoKey(FltCategory_.fcZero, FltCategory_.fcNormal)) {
            if (rhs.sign != 0) {
                return CmpResult_.cmpGreaterThan;
            }
            else {
                return CmpResult_.cmpLessThan;
            }
        }
        else if (pac == .PackCategoriesIntoKey(FltCategory_.fcInfinity, FltCategory_.fcInfinity)) {
            if (this.sign == rhs.sign) {
                return CmpResult_.cmpEqual;
            }
            else if (this.sign != 0) {
                return CmpResult_.cmpLessThan;
            }
            else {
                return CmpResult_.cmpGreaterThan;
            }
        }
        else if (pac == .PackCategoriesIntoKey(FltCategory_.fcZero, FltCategory_.fcZero)) {
            return CmpResult_.cmpEqual;
        }
        else if (pac == .PackCategoriesIntoKey(FltCategory_.fcNormal, FltCategory_.fcNormal)) {
        }
        else {
            assert(false, "null"c);
        }
        /* Two normal numbers.  Do they have the same sign?  */
        if (this.sign != rhs.sign) {
            if (this.sign != 0) {
                result = CmpResult_.cmpLessThan;
            }
            else {
                result = CmpResult_.cmpGreaterThan;
            }
        }
        else {
            /* Compare absolute values; invert result 如果 negative.  */
            result = this.compareAbsoluteValue(rhs);
            if (this.sign != 0) {
                if (result == CmpResult_.cmpLessThan) {
                    result = CmpResult_.cmpGreaterThan;
                }
                else if (result == CmpResult_.cmpGreaterThan) {
                    result = CmpResult_.cmpLessThan;
                }
            }
        }
        return result;
    }
    CmpResult_ compareAbsoluteValue(IEEEFloat_ rhs) {
        int _compare = this.exponent - rhs.exponent;
        /* If exponents are equal, do an unsigned bignum comparison of the
           significands.  */
        if (_compare == 0) {
            _compare = tcCompare(this.significand, rhs.significand, this.partCount());
        }
        if (_compare > 0) {
            return CmpResult_.cmpGreaterThan;
        }
        else if (_compare < 0) {
            return CmpResult_.cmpLessThan;
        }
        else {
            return CmpResult_.cmpEqual;
        }
    }
    ulong addSignificand(IEEEFloat_ rhs) {
        return tcAdd(this.significand, rhs.significand, 0, this.partCount());
    }
    ulong subtractSignificand(IEEEFloat_ rhs, ulong borrow) {
        return tcSubtract(this.significand, rhs.significand, borrow, this.partCount());
    }
    int exponentNaN() {
        return this.semantics.maxExponent + 1;
    }
    void makeNaN(bool SNaN, bool Negative, APInt_ fill = ··null!(APInt_)) {
        this.category = FltCategory_.fcNaN;
        this.sign = Negative ? 1 : 0;
        this.exponent = this.exponentNaN();
        uint numParts = this.partCount();
        // Set the _significand bits to the fill.
        if ((fill is ··null!(APInt_)) || fill.getNumWords() < numParts) {
            tcSet(this.significand, 0, numParts);
        }
        if (fill !is ··null!(APInt_)) {
            tcAssign(this.significand, fill.getRawData(), (cast(uint)(最小(fill.getNumWords(), numParts))));
            // Zero out the excess bits of the _significand.
            uint bitsToPreserve = this.semantics.precision - 1;
            uint part = bitsToPreserve / 64;
            bitsToPreserve %= 64;
            this.significand[part] &= ((1uL << bitsToPreserve) - 1);
            for (++part; part != numParts; ++part) {
                this.significand[part] = 0;
            }
        }
        uint QNaNBit = this.semantics.precision - 2;
        if (SNaN) {
            // We always have to clear the QNaN bit to make it an SNaN.
            tcClearBit(this.significand, QNaNBit);
            // If there are no bits set in the payload, we have to set
            // *something* to make it a NaN instead of an infinity;
            // conventionally, this is the next bit down from the QNaN bit.
            if (tcIsZero(this.significand, numParts)) {
                tcSetBit(this.significand, QNaNBit - 1);
            }
        }
        else {
            // We always have to set the QNaN bit to make it a QNaN.
            tcSetBit(this.significand, QNaNBit);
        }
        // For x87 extended precision, we want to make a NaN, not a
        // pseudo-NaN.  Maybe we should expose the ability to make
        // pseudo-NaNs?
        if (this.semantics == .semX87DoubleExtended) {
            tcSetBit(this.significand, QNaNBit + 1);
        }
    }
    bool convertFromStringSpecials(dstring str) {
        size_t MIN_NAME_SIZE = 3;
        if (str.length < MIN_NAME_SIZE) {
            return false;
        }
        if (str == "inf"d || str == "INFINITY"d || str == "+Inf"d) {
            this.makeInf(false);
            return true;
        }
        bool IsNegative = str[0] == 字符_.减号;
        if (IsNegative) {
            str = str[1 .. $];
            if (str.length < MIN_NAME_SIZE) {
                return false;
            }
            if (str == "inf"d || str == "INFINITY"d || str == "Inf"d) {
                this.makeInf(true);
                return true;
            }
        }
        // 如果 we have a 's' (or 'S') prefix, then this is a Signaling NaN.
        bool IsSignaling = str[0] == 字符_.s || str[0] == 字符_.S;
        if (IsSignaling) {
            str = str[1 .. $];
            if (str.length < MIN_NAME_SIZE) {
                return false;
            }
        }
        if (开始包含(str, "nan"d) || 开始包含(str, "NaN"d)) {
            str = str[3 .. $];
            // A NaN without payload.
            if ((str is ··null!(dstring)) || str == ""d) {
                this.makeNaN(IsSignaling, IsNegative);
                return true;
            }
            // Allow the payload to be inside parentheses.
            if (str[0] == 字符_.左括号) {
                // Parentheses should be balanced (and not empty).
                if (str.length <= 2 || str[str.length - 1] != 字符_.右括号) {
                    return false;
                }
                str = str[1 .. $-1];
            }
            // Determine the payload number's radix.
            ubyte Radix = 10;
            if (str[0] == 字符_.数_0) {
                if (str.length > 1 && (str[1] == 字符_.x || str[1] == 字符_.X)) {
                    str = str[2 .. $];
                    Radix = 16;
                }
                else {
                    Radix = 8;
                }
            }
            // Parse the payload and make the NaN.
            try {
                ulong un = 编译数字.编译!(ulong)(str, Radix);
                APInt_ Payload = new APInt_();
                Payload.Op等(un);
                this.makeNaN(IsSignaling, IsNegative, Payload);
                return true;
            }
            catch(Throwable _) {
                return false;
            }
        }
        return false;
    }
    OpStatus_ convertFromString(dstring str, RoundingMode_ rounding_mode) {
        if ((str is ··null!(dstring)) || str == ""d) {
            throw new Throwable(·to!(string)(("小数内容无效."d)));
        }
        // Handle special cases.
        if (this.convertFromStringSpecials(str)) {
            return OpStatus_.opOK;
        }
        /* Handle a leading minus sign.  */
        ulong 开始 = 0;
        immutable(dchar) p = str[开始];
        size_t slen = str.length;
        this.sign = p == 字符_.减号 ? 1 : 0;
        if (p == 字符_.减号 || p == 字符_.加号) {
            ++开始;
            if (开始 == slen) {
                throw new Throwable(·to!(string)(("小数内容无效."d)));
            }
        }
        if (开始 + 2 < slen && str[开始] == 字符_.数_0 && (str[开始 + 1] == 字符_.x || str[开始 + 1] == 字符_.X)) {
            if (开始 + 2 == slen) {
                throw new Throwable(·to!(string)(("小数内容无效."d)));
            }
            return this.convertFromHexadecimalString(str[开始 + 2 .. $], rounding_mode);
        }
        return this.convertFromDecimalString(str[开始 .. $], rounding_mode);
    }
    OpStatus_ convertFromHexadecimalString(dstring s, RoundingMode_ rounding_mode) {
        LostFraction_ lost_fraction = LostFraction_.lfExactlyZero;
        this.category = FltCategory_.fcNormal;
        this.zeroSignificand();
        this.exponent = 0;
        uint partsCount = this.partCount();
        uint bitPos = (cast(uint)(partsCount * .integerPartWidth));
        bool computedTrailingFraction = false;
        size_t end = s.length;
        ·Tuple!(ulong, ulong) PtrOrErr = .skipLeadingZeroesAndAnyDot(s);
        ulong 开始 = PtrOrErr[0];
        dchar p = (cast(dchar)(s[开始]));
        ulong dot = PtrOrErr[1];
        ulong firstSignificantDigit = 开始;
        while(开始 != end) {
            ulong hex_value;
            if (p == 字符_.点号) {
                if (dot != end) {
                    throw new Throwable(·to!(string)(("String contains multiple dots"d)));
                }
                dot = 开始;
                p = (cast(dchar)(s[++开始]));
                continue;
            }
            hex_value = hexDigitValue(p);
            if (hex_value == -1u) {
                break;
            }
            ++开始;
            if (开始 != s.length) {
                p = (cast(dchar)(s[开始]));
            }
            else {
                p = 字符_.空字符;
            }
            // Store the number 循环 we have space.
            if (bitPos != 0) {
                bitPos -= 4;
                hex_value <<= bitPos % .integerPartWidth;
                this.significand[bitPos / .integerPartWidth] |= hex_value;
            }
            else if (!computedTrailingFraction) {
                lost_fraction = .trailingHexadecimalFraction(s[开始 .. $], hex_value);
                computedTrailingFraction = true;
            }
        }
        /* Hex floats require an exponent but not a hexadecimal point.  */
        if (开始 == end) {
            throw new Throwable(·to!(string)(("Hex strings require an exponent"d)));
        }
        if (p != 字符_.p && p != 字符_.P) {
            throw new Throwable(·to!(string)(("Invalid character in significand"d)));
        }
        if (开始 == 0) {
            throw new Throwable(·to!(string)(("Significand has no digits"d)));
        }
        if (dot != end && 开始 == 1) {
            throw new Throwable(·to!(string)(("Significand has no digits"d)));
        }
        /* Ignore the exponent 如果 we are zero.  */
        if (开始 != firstSignificantDigit) {
            int expAdjustment = 0;
            /* Implicit hexadecimal point?  */
            if (dot == end) {
                --dot;
            }
            /* Calculate the exponent adjustment implicit in the number of
            significant digits.  */
            expAdjustment = (cast(int)(dot - firstSignificantDigit));
            if (expAdjustment < 0) {
                ++expAdjustment;
            }
            expAdjustment = expAdjustment * 4 - 1;
            /* Adjust 循环 writing the significand starting at the most
            significant nibble.  */
            expAdjustment += this.semantics.precision;
            expAdjustment -= partsCount * .integerPartWidth;
            /* Adjust 循环 the given exponent.  */
            this.exponent = .totalExponent(s[开始 + 1 .. $], expAdjustment);
        }
        return this.normalize(rounding_mode, lost_fraction);
    }
    OpStatus_ convertFromDecimalString(dstring str, RoundingMode_ rounding_mode) {
        OpStatus_ fs;
        /* Scan the text.  */
        _DecimalInfo_ DD = .interpretDecimal(str);
        if (DD.firstSigDigit == str.length || .decDigitValue(str[DD.firstSigDigit]) >= 10u) {
            this.category = FltCategory_.fcZero;
            fs = OpStatus_.opOK;
        }
        else if (DD.normalizedExponent - 1 > INT_MAX / 42039) {
            fs = this.handleOverflow(rounding_mode);
        }
        else if (DD.normalizedExponent - 1 < INT_MIN / 42039 || (DD.normalizedExponent + 1) * 28738 <= 8651 * (this.semantics.minExponent - (cast(int)(this.semantics.precision)))) {
            /* Underflow to zero and round.  */
            this.category = FltCategory_.fcNormal;
            this.zeroSignificand();
            fs = this.normalize(rounding_mode, LostFraction_.lfLessThanHalf);
        }
        else if ((DD.normalizedExponent - 1) * 42039 >= 12655 * this.semantics.maxExponent) {
            /* Overflow and round.  */
            fs = this.handleOverflow(rounding_mode);
        }
        else {
            ulong 开始 = 0;
            dchar p = (cast(dchar)(str[开始]));
            ulong[] decSignificand = 创建数组!(ulong)();
            uint _partCount;
            /* A tight upper bound on number of bits required to hold an
               N-digit decimal integer is N * 196 / 59.  Allocate enough space
               to hold the full significand, and an extra part required by
               tcMultiplyPart.
            */
            _partCount = (cast(uint)((DD.lastSigDigit - DD.firstSigDigit) + 1));
            _partCount = .partCountForBits(1 + 196 * _partCount / 59);
            decSignificand.length = _partCount + 1;
            _partCount = 0;
            /* Convert to binary efficiently - we do almost all multiplication
               in an integerPart.  When this would overflow do we do a single
               bignum multiplication, and then revert again to multiplication
               in an integerPart.
            */
            ulong decValue = 0;
            ulong val = 0;
            ulong multiplier = 0;
            bool 第一层 = false;
            while(!第一层 || 开始 <= DD.lastSigDigit) {
                第一层 = true;
                val = 0;
                multiplier = 1;
                bool 第二层 = false;
                while(!第二层 || 开始 <= DD.lastSigDigit && multiplier <= (~(cast(IntegerPart_)(0)) - 9) / 10) {
                    第二层 = true;
                    if (p == 字符_.点号) {
                        ++开始;
                        if (开始 == str.length) {
                            break;
                        }
                        p = (cast(dchar)(str[开始]));
                    }
                    decValue = .decDigitValue(p);
                    ++开始;
                    if (开始 < str.length) {
                        p = (cast(dchar)(str[开始]));
                    }
                    else {
                        p = 字符_.空字符;
                    }
                    if (decValue >= 10u) {
                        throw new Throwable(·to!(string)(("Invalid character in significand"d)));
                    }
                    multiplier *= 10;
                    val = val * 10 + decValue;
                }
                tcMultiplyPart(decSignificand, decSignificand, multiplier, val, _partCount, _partCount + 1, false);
                /* If we used another part (likely but not guaranteed), increase
                   the count.  */
                if (decSignificand[_partCount] != 0) {
                    ++_partCount;
                }
            }
            this.category = FltCategory_.fcNormal;
            fs = this.roundSignificandWithExponent(decSignificand, _partCount, DD.exponent, rounding_mode);
        }
        return fs;
    }
    OpStatus_ roundSignificandWithExponent(ulong[] decSigParts, uint sigPartCount, int exp, RoundingMode_ rounding_mode) {
        uint parts = 0;
        uint pow5PartCount = 0;
        FltSemantics_ calcSemantics = new FltSemantics_(32767, -32767, 0, 0);
        ulong[] pow5Parts = 创建数组!(ulong)();
        pow5Parts.length = .maxPowerOfFiveParts;
        bool isNearest = (rounding_mode == .rmNearestTiesToEven || rounding_mode == .rmNearestTiesToAway);
        parts = .partCountForBits(this.semantics.precision + 11);
        /* Calculate pow(5, abs(exp)).  */
        pow5PartCount = .powerOf5(pow5Parts, exp >= 0 ? exp : -exp);
        for (;; parts *= 2) {
            OpStatus_ sigStatus;
            OpStatus_ powStatus;
            uint excessPrecision = 0;
            uint truncatedBits = 0;
            calcSemantics.precision = (cast(uint)(parts * .integerPartWidth - 1));
            excessPrecision = calcSemantics.precision - this.semantics.precision;
            truncatedBits = excessPrecision;
            IEEEFloat_ decSig = new IEEEFloat_(calcSemantics, UninitializedTag_.uninitialized);
            decSig.makeZero(this.sign != 0);
            IEEEFloat_ pow5 = new IEEEFloat_(calcSemantics);
            sigStatus = decSig.convertFromUnsignedParts(decSigParts, sigPartCount, .rmNearestTiesToEven);
            powStatus = pow5.convertFromUnsignedParts(pow5Parts, pow5PartCount, .rmNearestTiesToEven);
            /* Add exp, as 10^n = 5^n * 2^n.  */
            decSig.exponent += exp;
            LostFraction_ calcLostFraction;
            ulong HUerr = 0;
            ulong HUdistance = 0;
            uint powHUerr = 0;
            if (exp >= 0) {
                /* multiplySignificand leaves the precision-th bit set to 1.  */
                calcLostFraction = decSig.multiplySignificand(pow5);
                powHUerr = powStatus != OpStatus_.opOK ? 1 : 0;
            }
            else {
                calcLostFraction = decSig.divideSignificand(pow5);
                /* Denormal numbers have less precision.  */
                if (decSig.exponent < this.semantics.minExponent) {
                    excessPrecision += (this.semantics.minExponent - decSig.exponent);
                    truncatedBits = excessPrecision;
                    if (excessPrecision > calcSemantics.precision) {
                        excessPrecision = calcSemantics.precision;
                    }
                }
                /* Extra half-ulp lost in reciprocal of exponent.  */
                powHUerr = (powStatus == OpStatus_.opOK && calcLostFraction == LostFraction_.lfExactlyZero) ? 0 : 2;
            }
            HUerr = .HUerrBound(calcLostFraction != LostFraction_.lfExactlyZero, sigStatus != OpStatus_.opOK ? 1 : 0, powHUerr);
            HUdistance = 2 * .ulpsFromBoundary(decSig.significand, excessPrecision, isNearest);
            /* Are we guaranteed to round correctly 如果 we truncate?  */
            if (HUdistance >= HUerr) {
                tcExtract(this.significand, this.partCount(), decSig.significand, calcSemantics.precision - excessPrecision, excessPrecision);
                /* Take the exponent of decSig.  If we tcExtract-ed less bits
                   above we must adjust our exponent to compensate 循环 the
                   implicit right shift.  */
                this.exponent = (decSig.exponent + this.semantics.precision - (calcSemantics.precision - excessPrecision));
                calcLostFraction = .lostFractionThroughTruncation(decSig.significand, decSig.partCount(), truncatedBits);
                return this.normalize(rounding_mode, calcLostFraction);
            }
        }
    }
    OpStatus_ multiply(IEEEFloat_ rhs, RoundingMode_ rounding_mode) {
        OpStatus_ fs;
        this.sign ^= rhs.sign;
        fs = this.multiplySpecials(rhs);
        if (this.isFiniteNonZero()) {
            LostFraction_ lost_fraction = this.multiplySignificand(rhs);
            fs = this.normalize(rounding_mode, lost_fraction);
            if (lost_fraction != LostFraction_.lfExactlyZero) {
                fs = .转换枚举!(OpStatus_)((cast(uint)(fs | OpStatus_.opInexact)));
            }
        }
        return fs;
    }
    LostFraction_ multiplySignificand(IEEEFloat_ rhs) {
        return this.multiplySignificand(rhs, new IEEEFloat_(rhs.semantics));
    }
    LostFraction_ multiplySignificand(IEEEFloat_ rhs, IEEEFloat_ addend) {
        ulong[] lhsSignificand = 创建数组!(ulong)();
        ulong[] fullSignificand = 创建数组!(ulong)();
        uint _precision = this.semantics.precision;
        // Allocate space 循环 twice as many bits as the original significand, plus one
        // extra bit 循环 the addition to overflow into.
        uint newPartsCount = .partCountForBits(_precision * 2 + 1);
        if (newPartsCount > 4) {
            fullSignificand.length = newPartsCount;
        }
        else {
            fullSignificand.length = 4;
        }
        uint _partsCount = this.partCount();
        tcFullMultiply(fullSignificand, this.significand, rhs.significand, _partsCount, _partsCount);
        LostFraction_ lost_fraction = LostFraction_.lfExactlyZero;
        uint omsb = tcMSB(fullSignificand, newPartsCount) + 1;
        this.exponent += rhs.exponent;
        // Assume the operands involved in the multiplication are single-_precision
        // FP, and the two multiplicants are:
        //   *this = a23 . a22 ... a0 * 2^e1
        //     rhs = b23 . b22 ... b0 * 2^e2
        // the result of multiplication is:
        //   *this = c48 c47 c46 . c45 ... c0 * 2^(e1+e2)
        // Note that there are three significant bits at the left-hand side of the
        // radix point: two 循环 the multiplication, and an overflow bit 循环 the
        // addition (that will always be zero at this point). Move the radix point
        // toward left by two bits, and adjust exponent accordingly.
        this.exponent += 2;
        if (addend.isNonZero()) {
            // The intermediate result of the multiplication has "2 * _precision"
            // signicant bit; adjust the addend to be consistent with mul result.
            //
            ulong[] savedSignificand = this.significand;
            FltSemantics_ savedSemantics = this.semantics;
            FltSemantics_ extendedSemantics;
            OpStatus_ status;
            uint extendedPrecision = 0;
            // Normalize our MSB to one below the top bit to allow 循环 overflow.
            extendedPrecision = 2 * _precision + 1;
            if (omsb != extendedPrecision - 1) {
                tcShiftLeft(fullSignificand, newPartsCount, (extendedPrecision - 1) - omsb);
                this.exponent -= (extendedPrecision - 1) - omsb;
            }
            /* Create new semantics.  */
            extendedSemantics = this.semantics;
            extendedSemantics.precision = extendedPrecision;
            if (newPartsCount == 1) {
                this.significand[0] = fullSignificand[0];
            }
            else {
                this.significand = fullSignificand;
            }
            this.semantics = extendedSemantics;
            // Make a copy so we can convert it to the extended semantics.
            // Note that we cannot convert the addend directly, as the extendedSemantics
            // is a local variable (which we take a reference to).
            IEEEFloat_ extendedAddend = new IEEEFloat_(addend);
            bool ignored = false;
            status = extendedAddend.convert(extendedSemantics, .rmTowardZero, ignored);
            // Shift the significand of the addend right by one bit. This guarantees
            // that the high bit of the significand is zero (same as fullSignificand),
            // so the addition will overflow (如果 it does overflow at all) into the top bit.
            lost_fraction = extendedAddend.shiftSignificandRight(1);
            lost_fraction = this.addOrSubtractSignificand(extendedAddend, false);
            /* Restore our state.  */
            if (newPartsCount == 1) {
                fullSignificand[0] = this.significand[0];
            }
            this.significand = savedSignificand;
            this.semantics = savedSemantics;
            omsb = tcMSB(fullSignificand, newPartsCount) + 1;
        }
        // Convert the result having "2 * _precision" significant-bits back to the one
        // having "_precision" significant-bits. First, move the radix point from
        // poision "2*_precision - 1" to "_precision - 1". The exponent need to be
        // adjusted by "2*_precision - 1" - "_precision - 1" = "_precision".
        this.exponent -= _precision + 1;
        // In case MSB resides at the left-hand side of radix point, shift the
        // mantissa right by some amount to make sure the MSB reside right before
        // the radix point (i.e. "MSB . rest-significant-bits").
        //
        // Note that the result is not normalized when "omsb < _precision". So, the
        // caller needs to call IEEEFloat_::normalize() 如果 normalized value is
        // expected.
        if (omsb > _precision) {
            uint bits;
            uint significantParts;
            LostFraction_ lf;
            bits = omsb - _precision;
            significantParts = .partCountForBits(omsb);
            lf = .shiftRight(fullSignificand, significantParts, bits);
            lost_fraction = .combineLostFractions(lf, lost_fraction);
            this.exponent += bits;
        }
        tcAssign(lhsSignificand, fullSignificand, _partsCount);
        return lost_fraction;
    }
    LostFraction_ divideSignificand(IEEEFloat_ rhs) {
        ulong[] dividend = 创建数组!(ulong)();
        ulong[] rhsSignificand = rhs.significandParts();
        uint _partsCount = this.partCount();
        if (_partsCount > 2) {
            dividend.length = _partsCount * 2;
        }
        else {
            dividend.length = 4;
        }
        .初始数据(dividend);
        ulong[] divisor = dividend[_partsCount .. $];
        uint i;
        /* Copy the dividend and divisor as they will be modified in-place.  */
        for (i = 0; i < _partsCount; ++i) {
            dividend[i] = this.significand[i];
            divisor[i] = rhsSignificand[i];
            this.significand[i] = 0;
        }
        this.exponent -= rhs.exponent;
        uint _precision = this.semantics.precision;
        /* Normalize the divisor.  */
        uint bit = _precision - tcMSB(divisor, _partsCount) - 1;
        if (bit != 0) {
            this.exponent += bit;
            tcShiftLeft(divisor, _partsCount, bit);
        }
        /* Normalize the dividend.  */
        bit = _precision - tcMSB(dividend, _partsCount) - 1;
        if (bit != 0) {
            this.exponent -= bit;
            tcShiftLeft(dividend, _partsCount, bit);
        }
        /* Ensure the dividend >= divisor initially 循环 the loop below.
           Incidentally, this means that the division loop below is
           guaranteed to set the integer bit to one.  */
        if (tcCompare(dividend, divisor, _partsCount) < 0) {
            --this.exponent;
            tcShiftLeft(dividend, _partsCount, 1);
        }
        /* Long division.  */
        for (bit = _precision; bit != 0; bit -= 1) {
            if (tcCompare(dividend, divisor, _partsCount) >= 0) {
                tcSubtract(dividend, divisor, 0, _partsCount);
                tcSetBit(this.significand, bit - 1);
            }
            tcShiftLeft(dividend, _partsCount, 1);
        }
        /* Figure out the lost fraction.  */
        int cmp = tcCompare(dividend, divisor, _partsCount);
        LostFraction_ lost_fraction;
        if (cmp > 0) {
            lost_fraction = LostFraction_.lfMoreThanHalf;
        }
        else if (cmp == 0) {
            lost_fraction = LostFraction_.lfExactlyHalf;
        }
        else if (tcIsZero(dividend, _partsCount)) {
            lost_fraction = LostFraction_.lfExactlyZero;
        }
        else {
            lost_fraction = LostFraction_.lfLessThanHalf;
        }
        return lost_fraction;
    }
    OpStatus_ convert(FltSemantics_ toSemantics, RoundingMode_ rounding_mode, ref bool losesInfo) {
        OpStatus_ fs;
        FltSemantics_ fromSemantics = this.semantics;
        LostFraction_ lostFraction = LostFraction_.lfExactlyZero;
        uint newPartCount = .partCountForBits(toSemantics.precision + 1);
        uint oldPartCount = this.partCount();
        int shift = toSemantics.precision - fromSemantics.precision;
        bool X86SpecialNan = false;
        if (fromSemantics == .semX87DoubleExtended && toSemantics != .semX87DoubleExtended && this.category == FltCategory_.fcNaN && ((this.significand[0] & 9223372036854775808uL) == 0 || (this.significand[0] & 4611686018427387904uL) == 0)) {
            // x86 has some unusual NaNs which cannot be represented in any other
            // format; note them here.
            X86SpecialNan = true;
        }
        // If this is a truncation of a denormal number, and the target semantics
        // has larger exponent range than the source semantics (this can happen
        // when truncating from PowerPC double-double to double format), the
        // right shift could lose result mantissa bits.  Adjust exponent instead
        // of performing excessive shift.
        if (shift < 0 && this.isFiniteNonZero()) {
            int exponentChange = this.significandMSB() + 1 - fromSemantics.precision;
            if (this.exponent + exponentChange < toSemantics.minExponent) {
                exponentChange = toSemantics.minExponent - this.exponent;
            }
            if (exponentChange < shift) {
                exponentChange = shift;
            }
            if (exponentChange < 0) {
                shift -= exponentChange;
                this.exponent += exponentChange;
            }
        }
        // If this is a truncation, perform the shift before we narrow the storage.
        if (shift < 0 && (this.isFiniteNonZero() || this.category == FltCategory_.fcNaN)) {
            lostFraction = .shiftRight(this.significand, oldPartCount, -shift);
        }
        // Fix the storage so it can hold to new value.
        if (newPartCount > oldPartCount) {
            // The new type requires more storage; make it available.
            ulong[] newParts = 创建数组!(ulong)();
            newParts.length = newPartCount;
            tcSet(newParts, 0, newPartCount);
            if (this.isFiniteNonZero() || this.category == FltCategory_.fcNaN) {
                tcAssign(newParts, this.significand, oldPartCount);
            }
            this.significand = newParts;
        }
        else if (newPartCount == 1 && oldPartCount != 1) {
            // Switch to built-in storage 循环 a single part.
            ulong newPart = 0;
            if (this.isFiniteNonZero() || this.category == FltCategory_.fcNaN) {
                newPart = this.significandParts()[0];
            }
            this.significand[0] = newPart;
        }
        // Now that we have the right storage, switch the semantics.
        this.semantics = toSemantics;
        // If this is an extension, perform the shift now that the storage is
        // available.
        if (shift > 0 && (this.isFiniteNonZero() || this.category == FltCategory_.fcNaN)) {
            tcShiftLeft(this.significand, newPartCount, shift);
        }
        if (this.isFiniteNonZero()) {
            fs = this.normalize(rounding_mode, lostFraction);
            losesInfo = (fs != OpStatus_.opOK);
        }
        else if (this.category == FltCategory_.fcNaN) {
            losesInfo = lostFraction != LostFraction_.lfExactlyZero || X86SpecialNan;
            // For x87 extended _precision, we want to make a NaN, not a special NaN 如果
            // the input wasn't special either.
            if (!X86SpecialNan && this.semantics == .semX87DoubleExtended) {
                tcSetBit(this.significand, this.semantics.precision - 1);
            }
            // Convert of sNaN creates qNaN and raises an exception (invalid op).
            // This also guarantees that a sNaN does not become Inf on a truncation
            // that loses all payload bits.
            if (this.isSignaling()) {
                this.makeQuiet();
                fs = OpStatus_.opInvalidOp;
            }
            else {
                fs = OpStatus_.opOK;
            }
        }
        else {
            losesInfo = false;
            fs = OpStatus_.opOK;
        }
        return fs;
    }
    dstring 打印(uint FormatPrecision, uint FormatMaxPadding, bool TruncateZero) {
        switch (this.category) {
            case FltCategory_.fcInfinity: {
                if (this.isNegative()) {
                    return "-Inf"d;
                }
                else {
                    return "+Inf"d;
                }
            }
            case FltCategory_.fcNaN: {
                return "NaN"d;
            }
            case FltCategory_.fcZero: {
                dstring s = ""d;
                if (this.isNegative()) {
                    s ~= "-"d;
                }
                if (FormatMaxPadding == 0) {
                    if (TruncateZero) {
                        s ~= "0.0E+0"d;
                    }
                    else {
                        s ~= "0.0"d;
                        if (FormatPrecision > 1) {
                            {
                                for (int i = 0; i < FormatPrecision; ++i) {
                                    s ~= "0"d;
                                }
                            }
                        }
                        s ~= "e+00"d;
                    }
                }
                else {
                    s ~= "0"d;
                }
                return s;
            }
            case FltCategory_.fcNormal: {
                break;
            }
            default: break;
        }
        dstring Str = ""d;
        if (this.isNegative()) {
            Str ~= "-"d;
        }
        // Decompose the number into an APInt_ and an exponent.
        int exp = this.exponent - ((cast(int)(this.semantics.precision)) - 1);
        ulong[] data = this.significand[0 .. .partCountForBits(this.semantics.precision)];
        APInt_ _significand = new APInt_(this.semantics.precision, data);
        if (FormatPrecision == 0) {
            FormatPrecision = 2 + this.semantics.precision * 59 / 196;
        }
        // Ignore trailing binary zeros.
        uint trailingZeros = _significand.countTrailingZeros();
        exp += trailingZeros;
        _significand.lshrInPlace(trailingZeros);
        // Change the exponent from 2^e to 10^e.
        if (exp == 0) {
        }
        else if (exp > 0) {
            // Just shift left.
            _significand = _significand.zext(this.semantics.precision + exp);
            _significand.Op左移等(exp);
            exp = 0;
        }
        else {
            /* exp < 0 */
            uint texp = -exp;
            // We transform 本体 using the identity:
            //   (N)(2^-e) == (N)(5^e)(10^-e)
            // This means we have to multiply N (the significand) by 5^e.
            // To avoid overflow, we have to operate on numbers large
            // enough to store N * 5^e:
            //   log2(N * 5^e) == log2(N) + e * log2(5)
            //                 <= semantics.precision + e * 137 / 59
            //   (log_2(5) ~ 2.321928 < 2.322034 ~ 137/59)
            uint precision = this.semantics.precision + (137 * texp + 136) / 59;
            // Multiply significand by 5^e.
            //   N * 5^0101 == N * 5^(1*1) * 5^(0*2) * 5^(1*4) * 5^(0*8)
            _significand = _significand.zext(precision);
            APInt_ five_to_the_i = new APInt_(precision, 5);
            while(true) {
                if ((texp & 1) != 0) {
                    _significand.Op乘等(five_to_the_i);
                }
                texp >>= 1;
                if (texp == 0) {
                    break;
                }
                five_to_the_i.Op乘等(five_to_the_i);
            }
        }
        .AdjustToPrecision_2(_significand, exp, FormatPrecision);
        dchar[] buffer = 创建数组!(dchar)();
        // Fill the buffer.
        uint _precision = _significand.BitWidth;
        APInt_ ten = new APInt_(_precision, 10);
        APInt_ digit = new APInt_(_precision, 0);
        bool inTrail = true;
        while(!_significand.Op等等(0)) {
            // digit <- significand % 10
            // significand <- significand / 10
            udivrem_2(_significand, ten, _significand, digit);
            uint d = (cast(uint)(digit.getZExtValue()));
            // Drop trailing zeros.
            if (inTrail && d == 0) {
                ++exp;
            }
            else {
                .追加!(dchar)(buffer, (cast(dchar)(cast(dchar)'0' + d)));
                inTrail = false;
            }
        }
        // Drop down to FormatPrecision.
        // TODO: don't do more precise calculations above than are required.
        .AdjustToPrecision(buffer, exp, FormatPrecision);
        uint NDigits = (cast(uint)(buffer.length));
        // Check whether we should use scientific notation.
        bool FormatScientific = false;
        if (FormatMaxPadding == 0) {
            FormatScientific = true;
        }
        else {
            if (exp >= 0) {
                // 765e3 -. 765000
                //              ^^^
                // But we shouldn't make the number look more precise than it is.
                FormatScientific = ((cast(uint)(exp)) > FormatMaxPadding || NDigits + (cast(uint)(exp)) > FormatPrecision);
            }
            else {
                // Power of the most significant digit.
                uint MSD = exp + (cast(uint)(NDigits - 1));
                if (MSD >= 0) {
                    // 765e-2 == 7.65
                    FormatScientific = false;
                }
                else {
                    // 765e-5 == 0.00765
                    //           ^ ^^
                    FormatScientific = (cast(uint)(-MSD)) > FormatMaxPadding;
                }
            }
        }
        // Scientific formatting is pretty straightforward.
        if (FormatScientific) {
            exp += (NDigits - 1);
            Str ~= ·to!(dstring)(buffer[NDigits - 1]);
            Str ~= "."d;
            if (NDigits == 1 && TruncateZero) {
                Str ~= "0"d;
            }
            else {
                {
                    for (uint I = 1; I != NDigits; ++I) {
                        Str ~= ·to!(dstring)(buffer[NDigits - 1 - I]);
                    }
                }
            }
            // Fill with zeros up to FormatPrecision.
            if (!TruncateZero && FormatPrecision > NDigits - 1) {
                {
                    for (int ii = 0; ii < FormatPrecision - NDigits + 1; ++ii) {
                        Str ~= "0"d;
                    }
                }
            }
            // For !TruncateZero we use lower 'e'.
            Str ~= (TruncateZero ? "E"d : "e"d).·to!(dstring)();
            Str ~= (exp >= 0 ? "+"d : "-"d).·to!(dstring)();
            if (exp < 0) {
                exp = -exp;
            }
            dchar[] expbuf = 创建数组!(dchar)();
            bool 第一层 = false;
            while(!第一层 || exp != 0) {
                第一层 = true;
                .追加!(dchar)(expbuf, (cast(dchar)(cast(dchar)'0' + (exp % 10))));
                exp /= 10;
            }
            // Exponent always at least two digits 如果 we do not truncate zeros.
            if (!TruncateZero && expbuf.length < 2) {
                .追加!(dchar)(expbuf, cast(dchar)'0');
            }
            {
                uint I = 0;
                size_t E = expbuf.length;
                for (; I != E; ++I) {
                    Str ~= ·to!(dstring)(expbuf[E - 1 - I]);
                }
            }
            return Str;
        }
        // Non-scientific, positive exponents.
        if (exp >= 0) {
            {
                for (uint I = 0; I != NDigits; ++I) {
                    Str ~= ·to!(dstring)(buffer[NDigits - 1 - I]);
                }
            }
            {
                for (uint I = 0; I != (cast(uint)(exp)); ++I) {
                    Str ~= "0"d;
                }
            }
            return Str;
        }
        // Non-scientific, negative exponents.
        // The number of digits to the left of the decimal point.
        int NWholeDigits = exp + (cast(int)(NDigits));
        uint I = 0;
        if (NWholeDigits > 0) {
            for (; I != (cast(uint)(NWholeDigits)); ++I) {
                Str ~= ·to!(dstring)(buffer[NDigits - I - 1]);
            }
            Str ~= "."d;
        }
        else {
            uint NZeros = 1 + (cast(uint)(-NWholeDigits));
            Str ~= "0"d;
            Str ~= "."d;
            {
                for (uint Z = 1; Z != NZeros; ++Z) {
                    Str ~= "0"d;
                }
            }
        }
        for (; I != NDigits; ++I) {
            Str ~= ·to!(dstring)(buffer[NDigits - I - 1]);
        }
        return Str;
    }
}
private class _DecimalInfo_ {
    ulong firstSigDigit;
    ulong lastSigDigit;
    int exponent;
    int normalizedExponent;
    this() {
        this.firstSigDigit = ··null!(ulong);
        this.lastSigDigit = ··null!(ulong);
        this.exponent = ··null!(int);
        this.normalizedExponent = ··null!(int);
    }
}
class DoubleAPFloat_ : APFloatBase_ {
    APFloat_[] Floats;
    this() {
        super();
        this.Floats = ··null!(APFloat_[]);
    }
    this(FltSemantics_ Semantics) {
        super();
        this.semantics = Semantics;
        this.Floats = [new APFloat_(.semIEEEdouble), new APFloat_(.semIEEEdouble)];
    }
    this(DoubleAPFloat_ R) {
        super();
        this.semantics = R.semantics;
        this.Floats = R.Floats;
    }
    this(FltSemantics_ Semantics, APFloat_[] Floats) {
        super();
        this.semantics = Semantics;
        this.Floats = Floats;
    }
    this(FltSemantics_ Semantics, APInt_ I) {
        this(Semantics, [new APFloat_(.semIEEEdouble, I.getRawData()[0]), new APFloat_(.semIEEEdouble, I.getRawData()[1])]);
    }
    OpStatus_ divide(DoubleAPFloat_ RHS, RoundingMode_ RM) {
        assert(this.semantics == .semPPCDoubleDouble, "Unexpected Semantics"c);
        APFloat_ Tmp = new APFloat_(.semPPCDoubleDoubleLegacy, this.bitcastToAPInt());
        OpStatus_ Ret = Tmp.divide(new APFloat_(.semPPCDoubleDoubleLegacy, RHS.bitcastToAPInt()), RM);
        DoubleAPFloat_ R = new DoubleAPFloat_(.semPPCDoubleDouble, Tmp.bitcastToAPInt());
        this.Floats = R.Floats;
        this.semantics = R.semantics;
        return Ret;
    }
    OpStatus_ mod(DoubleAPFloat_ RHS) {
        assert(this.semantics == .semPPCDoubleDouble, "Unexpected Semantics"c);
        APFloat_ Tmp = new APFloat_(.semPPCDoubleDoubleLegacy, this.bitcastToAPInt());
        OpStatus_ Ret = Tmp.mod(new APFloat_(.semPPCDoubleDoubleLegacy, RHS.bitcastToAPInt()));
        DoubleAPFloat_ R = new DoubleAPFloat_(.semPPCDoubleDouble, Tmp.bitcastToAPInt());
        this.Floats = R.Floats;
        this.semantics = R.semantics;
        return Ret;
    }
    OpStatus_ fusedMultiplyAdd(DoubleAPFloat_ Multiplicand, DoubleAPFloat_ Addend, RoundingMode_ RM) {
        assert(this.semantics == .semPPCDoubleDouble, "Unexpected Semantics"c);
        APFloat_ Tmp = new APFloat_(.semPPCDoubleDoubleLegacy, this.bitcastToAPInt());
        OpStatus_ Ret = Tmp.fusedMultiplyAdd(new APFloat_(.semPPCDoubleDoubleLegacy, Multiplicand.bitcastToAPInt()), new APFloat_(.semPPCDoubleDoubleLegacy, Addend.bitcastToAPInt()), RM);
        DoubleAPFloat_ R = new DoubleAPFloat_(.semPPCDoubleDouble, Tmp.bitcastToAPInt());
        this.Floats = R.Floats;
        this.semantics = R.semantics;
        return Ret;
    }
    OpStatus_ multiply(DoubleAPFloat_ RHS, RoundingMode_ RM) {
        DoubleAPFloat_ LHS = this;
        DoubleAPFloat_ Out = this;
        if (LHS.getCategory() == FltCategory_.fcNaN) {
            Out = LHS;
            return OpStatus_.opOK;
        }
        if (RHS.getCategory() == FltCategory_.fcNaN) {
            Out = RHS;
            return OpStatus_.opOK;
        }
        if (LHS.getCategory() == FltCategory_.fcZero && RHS.getCategory() == FltCategory_.fcInfinity || LHS.getCategory() == FltCategory_.fcInfinity && RHS.getCategory() == FltCategory_.fcZero) {
            Out.makeNaN(false, false);
            return OpStatus_.opOK;
        }
        if (LHS.getCategory() == FltCategory_.fcZero || RHS.getCategory() == FltCategory_.fcInfinity) {
            Out = LHS;
            return OpStatus_.opOK;
        }
        if (RHS.getCategory() == FltCategory_.fcZero || RHS.getCategory() == FltCategory_.fcInfinity) {
            Out = RHS;
            return OpStatus_.opOK;
        }
        OpStatus_ Status = OpStatus_.opOK;
        APFloat_ A = this.Floats[0];
        APFloat_ B = this.Floats[1];
        APFloat_ C = RHS.Floats[0];
        APFloat_ D_ = RHS.Floats[1];
        APFloat_ T = A;
        Status |= T.multiply(C, RM);
        if (!T.isFiniteNonZero()) {
            this.Floats[0] = T;
            this.Floats[1].makeZero(false);
            return Status;
        }
        APFloat_ Tau = A;
        T.changeSign();
        Status |= Tau.fusedMultiplyAdd(C, T, RM);
        T.changeSign();
        APFloat_ U = T;
        Status |= U.add(Tau, RM);
        this.Floats[0] = U;
        if (!U.isFinite()) {
            this.Floats[1].makeZero(/* Neg = */ false);
        }
        else {
            Status |= T.subtract(U, RM);
            Status |= T.add(Tau, RM);
        }
        return Status;
    }
    CmpResult_ compareAbsoluteValue(DoubleAPFloat_ RHS) {
        CmpResult_ Result = this.Floats[0].compareAbsoluteValue(RHS.Floats[0]);
        if (Result != CmpResult_.cmpEqual) {
            return Result;
        }
        Result = this.Floats[1].compareAbsoluteValue(RHS.Floats[1]);
        if (Result == CmpResult_.cmpLessThan || Result == CmpResult_.cmpGreaterThan) {
            int f0v = this.Floats[0].isNegative() ? 1 : 0;
            int f1v = this.Floats[1].isNegative() ? 1 : 0;
            int r0v = RHS.Floats[0].isNegative() ? 1 : 0;
            int r1v = RHS.Floats[1].isNegative() ? 1 : 0;
            int Against = f0v ^ f1v;
            int RHSAgainst = r0v ^ r1v;
            if (Against != 0 && RHSAgainst == 0) {
                return CmpResult_.cmpLessThan;
            }
            if (Against == 0 && RHSAgainst != 0) {
                return CmpResult_.cmpGreaterThan;
            }
            if (Against == 0 && RHSAgainst == 0) {
                return Result;
            }
            if (Against != 0 && RHSAgainst != 0) {
                CmpResult_ R = CmpResult_.cmpLessThan + CmpResult_.cmpGreaterThan - Result;
                return .转换枚举!(CmpResult_)(R);
            }
        }
        return Result;
    }
    OpStatus_ add(DoubleAPFloat_ RHS, RoundingMode_ RM) {
        DoubleAPFloat_ L = this;
        OpStatus_ R = this.addWithSpecial(this, RHS, L, RM);
        this.Floats = L.Floats;
        this.semantics = L.semantics;
        return R;
    }
    OpStatus_ addWithSpecial(DoubleAPFloat_ LHS, DoubleAPFloat_ RHS, ref DoubleAPFloat_ Out, RoundingMode_ RM) {
        if (LHS.getCategory() == FltCategory_.fcNaN) {
            Out = LHS;
            return OpStatus_.opOK;
        }
        if (RHS.getCategory() == FltCategory_.fcNaN) {
            Out = RHS;
            return OpStatus_.opOK;
        }
        if (LHS.getCategory() == FltCategory_.fcZero) {
            Out = RHS;
            return OpStatus_.opOK;
        }
        if (RHS.getCategory() == FltCategory_.fcZero) {
            Out = LHS;
            return OpStatus_.opOK;
        }
        if (LHS.getCategory() == FltCategory_.fcInfinity && RHS.getCategory() == FltCategory_.fcInfinity && LHS.isNegative() != RHS.isNegative()) {
            Out.makeNaN(false, Out.isNegative());
            return OpStatus_.opInvalidOp;
        }
        if (LHS.getCategory() == FltCategory_.fcInfinity) {
            Out = LHS;
            return OpStatus_.opOK;
        }
        if (RHS.getCategory() == FltCategory_.fcInfinity) {
            Out = RHS;
            return OpStatus_.opOK;
        }
        APFloat_ A = LHS.Floats[0];
        APFloat_ AA = LHS.Floats[1];
        APFloat_ C = RHS.Floats[0];
        APFloat_ CC = RHS.Floats[1];
        return Out.addImpl(A, AA, C, CC, RM);
    }
    OpStatus_ subtract(DoubleAPFloat_ RHS, RoundingMode_ RM) {
        this.changeSign();
        OpStatus_ Ret = this.add(RHS, RM);
        this.changeSign();
        return Ret;
    }
    OpStatus_ addImpl(APFloat_ a, APFloat_ aa, APFloat_ c, APFloat_ cc, RoundingMode_ RM) {
        OpStatus_ Status = OpStatus_.opOK;
        APFloat_ z = a;
        Status |= z.add(c, RM);
        if (!z.isFinite()) {
            if (!z.isInfinity()) {
                this.Floats[0] = z;
                this.Floats[1].makeZero(/* Neg = */ false);
                return Status;
            }
            Status = OpStatus_.opOK;
            CmpResult_ AComparedToC = a.compareAbsoluteValue(c);
            z = cc;
            Status |= z.add(aa, RM);
            if (AComparedToC == CmpResult_.cmpGreaterThan) {
                // z = cc + aa + c + a;
                Status |= z.add(c, RM);
                Status |= z.add(a, RM);
            }
            else {
                // z = cc + aa + a + c;
                Status |= z.add(a, RM);
                Status |= z.add(c, RM);
            }
            if (!z.isFinite()) {
                this.Floats[0] = z;
                this.Floats[1].makeZero(/* Neg = */ false);
                return Status;
            }
            this.Floats[0] = z;
            APFloat_ zz = aa;
            Status |= zz.add(cc, RM);
            if (AComparedToC == CmpResult_.cmpGreaterThan) {
                // 本体.Floats[1] = a - z + c + zz;
                this.Floats[1] = a;
                Status |= this.Floats[1].subtract(z, RM);
                Status |= this.Floats[1].add(c, RM);
                Status |= this.Floats[1].add(zz, RM);
            }
            else {
                // 本体.Floats[1] = c - z + a + zz;
                this.Floats[1] = c;
                Status |= this.Floats[1].subtract(z, RM);
                Status |= this.Floats[1].add(a, RM);
                Status |= this.Floats[1].add(zz, RM);
            }
        }
        else {
            // q = a - z;
            APFloat_ q = a;
            Status |= q.subtract(z, RM);
            // zz = q + c + (a - (q + z)) + aa + cc;
            // Compute a - (q + z) as -((q + z) - a) to avoid temporary copies.
            APFloat_ zz = q;
            Status |= zz.add(c, RM);
            Status |= q.add(z, RM);
            Status |= q.subtract(a, RM);
            q.changeSign();
            Status |= zz.add(q, RM);
            Status |= zz.add(aa, RM);
            Status |= zz.add(cc, RM);
            if (zz.isZero() && !zz.isNegative()) {
                this.Floats[0] = z;
                this.Floats[1].makeZero(/* Neg = */ false);
                return OpStatus_.opOK;
            }
            this.Floats[0] = z;
            Status |= this.Floats[0].add(zz, RM);
            if (!this.Floats[0].isFinite()) {
                this.Floats[1].makeZero(/* Neg = */ false);
                return Status;
            }
            this.Floats[1] = z;
            Status |= this.Floats[1].subtract(this.Floats[0], RM);
            Status |= this.Floats[1].add(zz, RM);
        }
        return Status;
    }
    void convertFromString(dstring Str, RoundingMode_ RN) {
        IEEEFloat_ Tmp = new IEEEFloat_(.semPPCDoubleDoubleLegacy);
        Tmp.convertFromString(Str, RN);
        DoubleAPFloat_ The = new DoubleAPFloat_(.semPPCDoubleDouble, Tmp.bitcastToAPInt());
    }
    APInt_ bitcastToAPInt() {
        assert(this.semantics == .semPPCDoubleDouble, "Unexpected Semantics"c);
        ulong[2] Data = [this.Floats[0].bitcastToAPInt().getRawData()[0], this.Floats[1].bitcastToAPInt().getRawData()[0]];
        return new APInt_(128, cast(ulong[])(Data));
    }
    OpStatus_ convertToInteger(ulong[] Input, uint Width, bool IsSigned, RoundingMode_ RM, ref bool IsExact) {
        assert(this.semantics == .semPPCDoubleDouble, "Unexpected Semantics"c);
        return (new APFloat_(.semPPCDoubleDoubleLegacy, this.bitcastToAPInt())).convertToInteger(Input, Width, IsSigned, RM, IsExact);
    }
    void makeInf(bool Neg) {
        (this.Floats[0]).makeInf(Neg);
        (this.Floats[1]).makeZero(false);
    }
    void makeNaN(bool SNaN, bool Neg, APInt_ fill = ··null!(APInt_)) {
        (this.Floats[0]).makeNaN(SNaN, Neg, fill);
        (this.Floats[1]).makeZero(false);
    }
    void makeZero(bool SNaN) {
        (this.Floats[0]).makeZero(SNaN);
        (this.Floats[1]).makeZero(false);
    }
    bool bitwiseIsEqual(DoubleAPFloat_ RHS) {
        return this.Floats[0].bitwiseIsEqual(RHS.Floats[0]) && this.Floats[1].bitwiseIsEqual(RHS.Floats[1]);
    }
    void changeSign() {
        this.Floats[0].changeSign();
        this.Floats[1].changeSign();
    }
    OpStatus_ convertFromAPInt(APInt_ Val, bool isSigned, RoundingMode_ rounding_mode) {
        assert(this.semantics == .semPPCDoubleDouble, "Unexpected Semantics"c);
        APFloat_ Tmp = new APFloat_(.semPPCDoubleDoubleLegacy);
        OpStatus_ Ret = Tmp.convertFromAPInt(Val, isSigned, rounding_mode);
        DoubleAPFloat_ Tmp2 = new DoubleAPFloat_(.semPPCDoubleDouble, Tmp.bitcastToAPInt());
        this.semantics = Tmp2.semantics;
        this.Floats = Tmp2.Floats;
        return Ret;
    }
    CmpResult_ compare(DoubleAPFloat_ RHS) {
        CmpResult_ Result = this.Floats[0].compare(RHS.Floats[0]);
        // |Float[0]| > |Float[1]|
        if (Result == CmpResult_.cmpEqual) {
            return this.Floats[1].compare(RHS.Floats[1]);
        }
        return Result;
    }
    FltCategory_ getCategory() {
        return this.Floats[0].getCategory();
    }
    bool isNegative() {
        return this.Floats[0].isNegative();
    }
    dstring 打印(uint FormatPrecision, uint FormatMaxPadding, bool TruncateZero) {
        APFloat_ F = new APFloat_(.semPPCDoubleDoubleLegacy, this.bitcastToAPInt());
        return F.打印(FormatPrecision, FormatMaxPadding, TruncateZero);
    }
}
class APFloat_ {
    APFloatBase_ U;
    this() { }
    this(APFloatBase_ U) {
        this.U = U;
    }
    this(double d) {
        this(new IEEEFloat_(d));
    }
    this(float f) {
        this(new IEEEFloat_(f));
    }
    this(FltSemantics_ Semantics) {
        if (this.f·usesLayout!(IEEEFloat_)(Semantics)) {
            this.U = new IEEEFloat_(Semantics);
        }
        else {
            this.U = new DoubleAPFloat_(Semantics);
        }
    }
    this(FltSemantics_ Semantics, ulong integerPart) {
        this.U = new IEEEFloat_(Semantics, integerPart);
    }
    this(FltSemantics_ Semantics, APInt_ apint) {
        this(Semantics);
        if (this.f·usesLayout!(IEEEFloat_)(Semantics)) {
            this.U = new IEEEFloat_(Semantics, apint);
        }
        else {
            this.U = new DoubleAPFloat_(Semantics, apint);
        }
    }
    this(FltSemantics_ Semantics, APFloat_[] Floats) {
        this.U = new DoubleAPFloat_(Semantics, Floats);
    }
    this(FltSemantics_ Semantics, dstring str) {
        this(Semantics);
        this.U = this.convertFromString(str, .rmNearestTiesToEven);
    }
    this(IEEEFloat_ F, FltSemantics_ S) {
        assert(S == .semPPCDoubleDouble, "xxx"c);
        this.U = new IEEEFloat_(F);
    }
    this(DoubleAPFloat_ DF, FltSemantics_ S) {
        assert(S == .semPPCDoubleDouble, "xxx"c);
        this.U = new DoubleAPFloat_(DF);
    }
    bool f·usesLayout(T)(FltSemantics_ Semantics) {
        static if (is(T == DoubleAPFloat_)) {
            return Semantics == .PPCDoubleDouble();
        }
        return Semantics != .PPCDoubleDouble();
    }
    IEEEFloat_ getIEEE() {
        if (this.f·usesLayout!(IEEEFloat_)(this.U.semantics)) {
            return (cast(IEEEFloat_)(this.U));
        }
        else {
            return (cast(IEEEFloat_)((cast(DoubleAPFloat_)(this.U)).Floats[0].U));
        }
    }
    dstring 打印(uint FormatPrecision, uint FormatMaxPadding, bool TruncateZero) {
        if (this.f·usesLayout!(IEEEFloat_)(this.U.semantics)) {
            return (cast(IEEEFloat_)(this.U)).打印(FormatPrecision, FormatMaxPadding, TruncateZero);
        }
        else {
            return (cast(DoubleAPFloat_)(this.U)).打印(FormatPrecision, FormatMaxPadding, TruncateZero);
        }
    }
    bool isSignaling() {
        return this.getIEEE().isSignaling();
    }
    APInt_ bitcastToAPInt() {
        if (this.f·usesLayout!(IEEEFloat_)(this.U.semantics)) {
            return (cast(IEEEFloat_)(this.U)).bitcastToAPInt();
        }
        else {
            return (cast(DoubleAPFloat_)(this.U)).bitcastToAPInt();
        }
    }
    OpStatus_ convertFromAPInt(APInt_ Val, bool isSigned, RoundingMode_ rounding_mode) {
        if (this.f·usesLayout!(IEEEFloat_)(this.U.semantics)) {
            return (cast(IEEEFloat_)(this.U)).convertFromAPInt(Val, isSigned, rounding_mode);
        }
        else {
            return (cast(DoubleAPFloat_)(this.U)).convertFromAPInt(Val, isSigned, rounding_mode);
        }
    }
    void makeInf(bool Neg) {
        if (this.f·usesLayout!(IEEEFloat_)(this.U.semantics)) {
            return (cast(IEEEFloat_)(this.U)).makeInf(Neg);
        }
        else {
            return (cast(DoubleAPFloat_)(this.U)).makeInf(Neg);
        }
    }
    void makeNaN(bool SNaN, bool Neg, APInt_ fill = ··null!(APInt_)) {
        if (this.f·usesLayout!(IEEEFloat_)(this.U.semantics)) {
            return (cast(IEEEFloat_)(this.U)).makeNaN(SNaN, Neg, fill);
        }
        else {
            return (cast(DoubleAPFloat_)(this.U)).makeNaN(SNaN, Neg, fill);
        }
    }
    void makeZero(bool Neg) {
        if (this.f·usesLayout!(IEEEFloat_)(this.U.semantics)) {
            return (cast(IEEEFloat_)(this.U)).makeZero(Neg);
        }
        else {
            return (cast(DoubleAPFloat_)(this.U)).makeZero(Neg);
        }
    }
    OpStatus_ convert(FltSemantics_ ToSemantics, RoundingMode_ RM, ref bool losesInfo) {
        if (this.getSemantics() == ToSemantics) {
            losesInfo = false;
            return OpStatus_.opOK;
        }
        if (this.f·usesLayout!(IEEEFloat_)(this.getSemantics()) && this.f·usesLayout!(IEEEFloat_)(ToSemantics)) {
            return (cast(IEEEFloat_)(this.U)).convert(ToSemantics, RM, losesInfo);
        }
        if (this.f·usesLayout!(IEEEFloat_)(this.getSemantics()) && this.f·usesLayout!(DoubleAPFloat_)(ToSemantics)) {
            OpStatus_ Ret = (cast(IEEEFloat_)(this.U)).convert(.semPPCDoubleDoubleLegacy, RM, losesInfo);
            this.U = (new APFloat_(ToSemantics, (cast(IEEEFloat_)(this.U)).bitcastToAPInt())).U;
            return Ret;
        }
        if (this.f·usesLayout!(DoubleAPFloat_)(this.getSemantics()) && this.f·usesLayout!(IEEEFloat_)(ToSemantics)) {
            OpStatus_ Ret = this.getIEEE().convert(ToSemantics, RM, losesInfo);
            this.U = (new APFloat_(this.getIEEE(), ToSemantics)).U;
            return Ret;
        }
        return OpStatus_.opOK;
    }
    APFloatBase_ convertFromString(dstring Str, RoundingMode_ RN) {
        if (this.f·usesLayout!(IEEEFloat_)(this.U.semantics)) {
            (cast(IEEEFloat_)(this.U)).convertFromString(Str, RN);
            return this.U;
        }
        else {
            (cast(DoubleAPFloat_)(this.U)).convertFromString(Str, RN);
            return this.U;
        }
    }
    FltSemantics_ getSemantics() {
        return this.U.semantics;
    }
    void changeSign() {
        if (!this.isNegative()) {
            return;
        }
        if (this.f·usesLayout!(IEEEFloat_)(this.U.semantics)) {
            return (cast(IEEEFloat_)(this.U)).changeSign();
        }
        else {
            return (cast(DoubleAPFloat_)(this.U)).changeSign();
        }
    }
    bool bitwiseIsEqual(APFloat_ RHS) {
        if (this.getSemantics() != RHS.getSemantics()) {
            return false;
        }
        if (this.f·usesLayout!(IEEEFloat_)(this.U.semantics)) {
            return (cast(IEEEFloat_)(this.U)).bitwiseIsEqual((cast(IEEEFloat_)(RHS.U)));
        }
        else {
            return (cast(DoubleAPFloat_)(this.U)).bitwiseIsEqual((cast(DoubleAPFloat_)(RHS.U)));
        }
    }
    OpStatus_ convertToInteger(ulong[] Input, uint Width, bool IsSigned, RoundingMode_ RM, ref bool IsExact) {
        if (this.f·usesLayout!(IEEEFloat_)(this.U.semantics)) {
            return (cast(IEEEFloat_)(this.U)).convertToInteger(Input, Width, IsSigned, RM, IsExact);
        }
        else {
            return (cast(DoubleAPFloat_)(this.U)).convertToInteger(Input, Width, IsSigned, RM, IsExact);
        }
    }
    OpStatus_ convertToInteger(ref APSInt_ result, RoundingMode_ rounding_mode, ref bool isExact) {
        uint bitWidth = result.getBitWidth();
        ulong[] parts = 创建数组!(ulong)();
        parts.length = result.getNumWords();
        APSInt_ R = (cast(APSInt_)(result));
        OpStatus_ status = this.convertToInteger(parts, bitWidth, R.isSigned(), rounding_mode, isExact);
        // Keeps the original signed-ness.
        result = new APSInt_(new APInt_(bitWidth, parts), false);
        return status;
    }
    CmpResult_ compare(APFloat_ RHS) {
        if (this.f·usesLayout!(IEEEFloat_)(this.U.semantics)) {
            return (cast(IEEEFloat_)(this.U)).compare((cast(IEEEFloat_)(RHS.U)));
        }
        else {
            return (cast(DoubleAPFloat_)(this.U)).compare((cast(DoubleAPFloat_)(RHS.U)));
        }
    }
    OpStatus_ add(APFloat_ RHS, RoundingMode_ RM) {
        if (this.f·usesLayout!(IEEEFloat_)(this.U.semantics)) {
            return (cast(IEEEFloat_)(this.U)).add((cast(IEEEFloat_)(RHS.U)), RM);
        }
        else {
            return (cast(DoubleAPFloat_)(this.U)).add((cast(DoubleAPFloat_)(RHS.U)), RM);
        }
    }
    OpStatus_ multiply(APFloat_ RHS, RoundingMode_ RM) {
        if (this.f·usesLayout!(IEEEFloat_)(this.U.semantics)) {
            return (cast(IEEEFloat_)(this.U)).multiply((cast(IEEEFloat_)(RHS.U)), RM);
        }
        else {
            return (cast(DoubleAPFloat_)(this.U)).multiply((cast(DoubleAPFloat_)(RHS.U)), RM);
        }
    }
    OpStatus_ divide(APFloat_ RHS, RoundingMode_ RM) {
        if (this.f·usesLayout!(IEEEFloat_)(this.U.semantics)) {
            return (cast(IEEEFloat_)(this.U)).divide((cast(IEEEFloat_)(RHS.U)), RM);
        }
        else {
            return (cast(DoubleAPFloat_)(this.U)).divide((cast(DoubleAPFloat_)(RHS.U)), RM);
        }
    }
    OpStatus_ mod(APFloat_ RHS) {
        if (this.f·usesLayout!(IEEEFloat_)(this.U.semantics)) {
            return (cast(IEEEFloat_)(this.U)).mod((cast(IEEEFloat_)(RHS.U)));
        }
        else {
            return (cast(DoubleAPFloat_)(this.U)).mod((cast(DoubleAPFloat_)(RHS.U)));
        }
    }
    OpStatus_ fusedMultiplyAdd(APFloat_ Multiplicand, APFloat_ Addend, RoundingMode_ RM) {
        if (this.f·usesLayout!(IEEEFloat_)(this.U.semantics)) {
            return (cast(IEEEFloat_)(this.U)).fusedMultiplyAdd((cast(IEEEFloat_)(Multiplicand.U)), (cast(IEEEFloat_)(Addend.U)), RM);
        }
        else {
            return (cast(DoubleAPFloat_)(this.U)).fusedMultiplyAdd((cast(DoubleAPFloat_)(Multiplicand.U)), (cast(DoubleAPFloat_)(Addend.U)), RM);
        }
    }
    CmpResult_ compareAbsoluteValue(APFloat_ RHS) {
        if (this.f·usesLayout!(IEEEFloat_)(this.U.semantics)) {
            return (cast(IEEEFloat_)(this.U)).compareAbsoluteValue((cast(IEEEFloat_)(RHS.U)));
        }
        else {
            return (cast(DoubleAPFloat_)(this.U)).compareAbsoluteValue((cast(DoubleAPFloat_)(RHS.U)));
        }
    }
    OpStatus_ subtract(APFloat_ RHS, RoundingMode_ RM) {
        if (this.f·usesLayout!(IEEEFloat_)(this.U.semantics)) {
            return (cast(IEEEFloat_)(this.U)).subtract((cast(IEEEFloat_)(RHS.U)), RM);
        }
        else {
            return (cast(DoubleAPFloat_)(this.U)).subtract((cast(DoubleAPFloat_)(RHS.U)), RM);
        }
    }
    FltCategory_ getCategory() {
        return this.getIEEE().getCategory();
    }
    bool isZero() {
        return this.getCategory() == FltCategory_.fcZero;
    }
    bool isNegative() {
        return this.getIEEE().isNegative();
    }
    bool isNegZero() {
        return this.isZero() && this.isNegative();
    }
    bool isPosZero() {
        return this.isZero() && !this.isNegative();
    }
    bool isInfinity() {
        return this.getCategory() == FltCategory_.fcInfinity;
    }
    bool isFinite() {
        return !this.isNaN() && !this.isInfinity();
    }
    bool isNaN() {
        return this.getCategory() == FltCategory_.fcNaN;
    }
    bool isFiniteNonZero() {
        return this.isFinite() && !this.isZero();
    }
}
LostFraction_ lostFractionThroughTruncation(ulong[] parts, uint partCount, uint bits) {
    uint lsb = tcLSB(parts, partCount);
    /* Note this is guaranteed true 如果 bits == 0, or LSB == -1U.  */
    if (bits <= lsb) {
        return LostFraction_.lfExactlyZero;
    }
    if (bits == lsb + 1) {
        return LostFraction_.lfExactlyHalf;
    }
    if (bits <= partCount * .integerPartWidth && tcExtractBit(parts, bits - 1)) {
        return LostFraction_.lfMoreThanHalf;
    }
    return LostFraction_.lfLessThanHalf;
}
LostFraction_ shiftRight(ref ulong[] dst, uint parts, uint bits) {
    LostFraction_ lost_fraction = .lostFractionThroughTruncation(dst, parts, bits);
    tcShiftRight(dst, parts, bits);
    return lost_fraction;
}
LostFraction_ combineLostFractions(LostFraction_ moreSignificant, LostFraction_ lessSignificant) {
    if (lessSignificant != LostFraction_.lfExactlyZero) {
        if (moreSignificant == LostFraction_.lfExactlyZero) {
            moreSignificant = LostFraction_.lfLessThanHalf;
        }
        else if (moreSignificant == LostFraction_.lfExactlyHalf) {
            moreSignificant = LostFraction_.lfMoreThanHalf;
        }
    }
    return moreSignificant;
}
ulong PackCategoriesIntoKey(ulong 左, ulong 右) {
    return 左 * 4 + 右;
}
uint partCountForBits(uint bits) {
    return (cast(uint)(((bits) + .integerPartWidth - 1) / .integerPartWidth));
}
int decDigitValue(const(dchar) c) {
    return (cast(int)(c - 字符_.数_0));
}
uint HUerrBound(bool inexactMultiply, uint HUerr1, uint HUerr2) {
    uint n = inexactMultiply ? 1 : 0;
    if (HUerr1 + HUerr2 == 0) {
        return n * 2; /* <= inexactMultiply half-ulps.  */
    }
    else {
        return n + 2 * (HUerr1 + HUerr2);
    }
}
Semantics_ SemanticsToEnum(FltSemantics_ Sem) {
    if (Sem == .IEEEhalf()) {
        return Semantics_.S_IEEEhalf;
    }
    else if (Sem == .BFloat()) {
        return Semantics_.S_BFloat;
    }
    else if (Sem == .IEEEsingle()) {
        return Semantics_.S_IEEEsingle;
    }
    else if (Sem == .IEEEdouble()) {
        return Semantics_.S_IEEEdouble;
    }
    else if (Sem == .x87DoubleExtended()) {
        return Semantics_.S_x87DoubleExtended;
    }
    else if (Sem == .IEEEquad()) {
        return Semantics_.S_IEEEquad;
    }
    else if (Sem == .PPCDoubleDouble()) {
        return Semantics_.S_PPCDoubleDouble;
    }
    return Semantics_.S_None;
}
FltSemantics_ IEEEhalf() {
    return .semIEEEhalf;
}
FltSemantics_ BFloat() {
    return .semBFloat;
}
FltSemantics_ IEEEsingle() {
    return .semIEEEsingle;
}
FltSemantics_ IEEEdouble() {
    return .semIEEEdouble;
}
FltSemantics_ IEEEquad() {
    return .semIEEEquad;
}
FltSemantics_ x87DoubleExtended() {
    return .semX87DoubleExtended;
}
FltSemantics_ Bogus() {
    return .semBogus;
}
FltSemantics_ PPCDoubleDouble() {
    return .semPPCDoubleDouble;
}
uint semanticsPrecision(FltSemantics_ semantics) {
    return semantics.precision;
}
int semanticsMaxExponent(FltSemantics_ semantics) {
    return semantics.maxExponent;
}
int semanticsMinExponent(FltSemantics_ semantics) {
    return semantics.minExponent;
}
uint semanticsSizeInBits(FltSemantics_ semantics) {
    return semantics.sizeInBits;
}
uint getSizeInBits(FltSemantics_ Sem) {
    return Sem.sizeInBits;
}
int ilogb(IEEEFloat_ Arg) {
    if (Arg.isNaN()) {
        return (cast(int)(IlogbErrorKinds_.IEK_NaN));
    }
    if (Arg.isZero()) {
        return (cast(int)(IlogbErrorKinds_.IEK_Zero));
    }
    if (Arg.isInfinity()) {
        return (cast(int)(IlogbErrorKinds_.IEK_Inf));
    }
    if (Arg.isDenormal()) {
        return Arg.exponent;
    }
    IEEEFloat_ Normalized = new IEEEFloat_(Arg);
    uint SignificandBits = Arg.getSemantics().precision - 1;
    Normalized.exponent += SignificandBits;
    Normalized.normalize(.rmNearestTiesToEven, LostFraction_.lfExactlyZero);
    return Normalized.exponent - SignificandBits;
}
IEEEFloat_ scalbn(IEEEFloat_ X, int Exp, RoundingMode_ RoundingMode) {
    int MaxExp = X.getSemantics().maxExponent;
    int MinExp = X.getSemantics().minExponent;
    // If Exp is wildly out-of-scale, simply adding it to X.exponent will
    // overflow; clamp it to a safe range before adding, but ensure that the range
    // is large enough that the clamp does not change the result. The range we
    // need to support is the difference between the largest possible exponent and
    // the normalized exponent of half the smallest denormal.
    int SignificandBits = X.getSemantics().precision - 1;
    int MaxIncrement = MaxExp - (MinExp - SignificandBits) + 1;
    // Clamp to one past the range ends to let normalize handle overlflow.
    X.exponent += (cast(int)(最小(最大(Exp, -MaxIncrement - 1), MaxIncrement)));
    X.normalize(RoundingMode, LostFraction_.lfExactlyZero);
    if (X.isNaN()) {
        X.makeQuiet();
    }
    return X;
}
void 初始数据(ref ulong[] ns) {
    {
        for (int i = 0; i < ns.length; ++i) {
            ns[i] = 0;
        }
    }
}
ulong ulpsFromBoundary(ulong[] parts, uint bits, bool isNearest) {
    --bits;
    uint count = (cast(uint)(bits / .integerPartWidth));
    uint partBits = (cast(uint)(bits % .integerPartWidth + 1));
    ulong boundary = isNearest ? (cast(IntegerPart_)(1)) << (partBits - 1) : 0;
    ulong part = parts[count] & (~(cast(IntegerPart_)(0)) >> (.integerPartWidth - partBits));
    if (count == 0) {
        if (part - boundary <= boundary - part) {
            return part - boundary;
        }
        else {
            return boundary - part;
        }
    }
    if (part == boundary) {
        while((--count) != 0) {
            if (parts[count] != 0) {
                return ~(cast(IntegerPart_)(0)); /* A lot.  */
            }
        }
        return parts[0];
    }
    else if (part == boundary - 1) {
        while((--count) != 0) {
            if ((~parts[count]) != 0) {
                return ~(cast(IntegerPart_)(0)); /* A lot.  */
            }
        }
        return -parts[0];
    }
    return ~(cast(IntegerPart_)(0)); /* A lot.  */
}
_DecimalInfo_ _createDecimalInfo_(ulong 开始) {
    _DecimalInfo_ DD = new _DecimalInfo_();
    DD.firstSigDigit = 开始;
    DD.exponent = 0;
    DD.normalizedExponent = 0;
    return DD;
}
_DecimalInfo_ interpretDecimal(dstring str) {
    ulong end = str.length;
    ulong dot = end;
    ·Tuple!(ulong, ulong) pAndDot = .skipLeadingZeroesAndAnyDot(str);
    ulong 开始 = pAndDot[0];
    dot = pAndDot[1];
    _DecimalInfo_ DD = ._createDecimalInfo_(开始);
    for (; 开始 != end; ++开始) {
        if (str[开始] == 字符_.点号) {
            if (dot != end) {
                throw new Throwable(·to!(string)(("String contains multiple dots"d)));
            }
            dot = 开始;
            ++开始;
            if (开始 == end) {
                break;
            }
        }
        if (.decDigitValue(str[开始]) >= 10u) {
            break;
        }
    }
    if (开始 != end) {
        if (str[开始] != 字符_.e && str[开始] != 字符_.E) {
            throw new Throwable(·to!(string)(("Invalid character in significand"d)));
        }
        if (开始 == 0) {
            throw new Throwable(·to!(string)(("Significand has no digits"d)));
        }
        if (dot != end && 开始 == 2) {
            throw new Throwable(·to!(string)(("Significand has no digits"d)));
        }
        DD.exponent = .readExponent(str[开始 + 1 .. $]);
        /* Implied decimal point?  */
        if (dot == end) {
            dot = 开始;
        }
    }
    /* If number is all zeroes accept any exponent.  */
    if (开始 != DD.firstSigDigit) {
        /* Drop insignificant trailing zeroes.  */
        if (开始 != 0) {
            bool 第一层 = false;
            while(!第一层 || 开始 != 0 && str[开始] == 字符_.数_0) {
                第一层 = true;
                bool 第二层 = false;
                while(!第二层 || 开始 != 0 && str[开始] == 字符_.点号) {
                    第二层 = true;
                    --开始;
                }
            }
        }
        /* Adjust the exponents 循环 any decimal point.  */
        DD.exponent += (cast(uint)((dot - 开始) - ((dot > 开始) ? 1 : 0)));
        DD.normalizedExponent = (cast(uint)((DD.exponent + ((开始 - DD.firstSigDigit) - ((dot > DD.firstSigDigit && dot < 开始) ? 1 : 0)))));
    }
    DD.lastSigDigit = 开始;
    return DD;
}
T 转换枚举(T)(uint opc) {
    return bitTo!(T, uint)(opc);
}
int readExponent(dstring str) {
    uint overlargeExponent = 24000; /* FIXME.  */
    ulong 开始 = 0;
    size_t end = str.length;
    // Treat no exponent as 0 to match binutils
    if (开始 == end) {
        return 0;
    }
    dchar p = (cast(dchar)(str[开始]));
    if (((p == 字符_.减号 || p == 字符_.加号) && (开始 + 1) == end)) {
        return 0;
    }
    bool isNegative = (p == 字符_.减号);
    if (p == 字符_.减号 || p == 字符_.加号) {
        p = (cast(dchar)(str[++开始]));
        if (开始 == end) {
            throw new Throwable(·to!(string)(("Exponent has no digits"d)));
        }
    }
    uint absExponent = .decDigitValue(p);
    p = (cast(dchar)(str[++开始]));
    if (absExponent >= 10u) {
        throw new Throwable(·to!(string)(("Invalid character in exponent"d)));
    }
    for (; 开始 != end; ++开始) {
        p = (cast(dchar)(str[开始]));
        uint value = .decDigitValue(p);
        if (value >= 10u) {
            throw new Throwable(·to!(string)(("Invalid character in exponent"d)));
        }
        absExponent = absExponent * 10u + value;
        if (absExponent >= overlargeExponent) {
            absExponent = overlargeExponent;
            break;
        }
    }
    if (isNegative) {
        return -(cast(int)(absExponent));
    }
    else {
        return (cast(int)(absExponent));
    }
}
void AdjustToPrecision_2(ref APInt_ significand, uint exp, uint FormatPrecision) {
    uint bits = significand.getActiveBits();
    // 196/59 is a very slight overestimate of lg_2(10).
    uint bitsRequired = (FormatPrecision * 196 + 58) / 59;
    if (bits <= bitsRequired) {
        return;
    }
    uint tensRemovable = (bits - bitsRequired) * 59 / 196;
    if (tensRemovable == 0) {
        return;
    }
    exp += tensRemovable;
    APInt_ divisor = new APInt_(significand.BitWidth, (cast(uint)(1)));
    APInt_ powten = new APInt_(significand.BitWidth, (cast(uint)(10)));
    while(true) {
        if ((tensRemovable & 1) != 0) {
            divisor.Op乘等(powten);
        }
        tensRemovable >>= 1;
        if (tensRemovable == 0) {
            break;
        }
        powten.Op乘等(powten);
    }
    significand = significand.udiv(divisor);
    // Truncate the significand down to its active bit count.
    significand = significand.trunc(significand.getActiveBits());
}
void AdjustToPrecision(ref dchar[] buffer, uint exp, uint FormatPrecision) {
    uint N = (cast(uint)(buffer.length));
    if (N <= FormatPrecision) {
        return // The most significant figures are the last ones in the buffer.
        ;
    }
    // The most significant figures are the last ones in the buffer.
    uint FirstSignificant = N - FormatPrecision;
    // Round.
    // FIXME: 本体 probably shouldn't use 'round half up'.
    // Rounding down is just a truncation, except we also want to drop
    // trailing zeros from the new result.
    if (buffer[FirstSignificant - 1] < cast(dchar)'5') {
        while(FirstSignificant < N && buffer[FirstSignificant] == cast(dchar)'0') {
            ++FirstSignificant;
        }
        exp += FirstSignificant;
        buffer = buffer[FirstSignificant .. $];
        return;
    }
    {
        // Rounding up requires a decimal add-with-carry.  If we continue
        // the carry, the newly-introduced zeros will just be truncated.
        for (uint I = FirstSignificant; I != N; ++I) {
            if (buffer[I] == cast(dchar)'9') {
                ++FirstSignificant;
            }
            else {
                uint ii = (cast(uint)(buffer[I]));
                buffer[I] = (cast(dchar)(++ii));
                break;
            }
        }
    }
    // If we carried through, we have exactly one digit of precision.
    if (FirstSignificant == N) {
        exp += FirstSignificant;
        buffer.length = 0;
        .追加!(dchar)(buffer, cast(dchar)'1');
        return;
    }
    exp += FirstSignificant;
    buffer = buffer[FirstSignificant .. $];
}
uint powerOf5(ulong[] dst, uint power) {
    ulong[] firstEightPowers = [1, 5, 25, 125, 625, 3125, 15625, 78125];
    ulong[] pow5s = 创建数组!(ulong)();
    pow5s.length = .maxPowerOfFiveParts * 2 + 5;
    pow5s[0] = 78125 * 5;
    uint[] partsCount = 创建数组!(uint)();
    partsCount.length = 16;
    partsCount[0] = 1;
    ulong[] p1 = 创建数组!(ulong)();
    ulong[] p2 = 创建数组!(ulong)();
    p2.length = .maxPowerOfFiveParts;
    ulong[] pow5 = 创建数组!(ulong)();
    uint result;
    p1 = dst;
    p1[0] = firstEightPowers[power & 7];
    power >>= 3;
    result = 1;
    pow5 = pow5s;
    uint 开始 = 0;
    {
        for (uint n = 0; power != 0; power >>= 1, ++n) {
            uint pc = partsCount[n];
            ulong[] 储存 = pow5;
            /* Calculate pow(5,pow(2,n+3)) 如果 we haven't yet.  */
            if (pc == 0) {
                pc = partsCount[n - 1];
                tcFullMultiply(pow5, 储存, 储存, pc, pc);
                pc *= 2;
                if (pow5[pc - 1] == 0) {
                    --pc;
                }
                partsCount[n] = pc;
            }
            if ((power & 1) != 0) {
                ulong[] tmp = 创建数组!(ulong)();
                tcFullMultiply(p2, p1, pow5, result, pc);
                result += pc;
                if (p2[result - 1] == 0) {
                    --result;
                }
                /* Now result is in p1 with partsCount parts and p2 is scratch
                   space.  */
                tmp = p1;
                p1 = p2;
                p2 = tmp;
            }
            开始 += pc;
            pow5 = pow5[pc .. $];
        }
    }
    if (p1 != dst) {
        tcAssign(dst, p1, result);
    }
    return result;
}
auto skipLeadingZeroesAndAnyDot(dstring s) {
    ulong 开始 = 0;
    dchar p = (cast(dchar)(s[开始]));
    size_t len = s.length;
    size_t dot = len;
    while(开始 != len && p == 字符_.数_0) {
        p = (cast(dchar)(s[++开始]));
    }
    if (开始 != len && p == 字符_.点号) {
        dot = 开始;
        ++开始;
        if (len - 开始 == 1) {
            throw new Throwable(·to!(string)(("Significand has no digits"d)));
        }
        while(开始 != len && p == 字符_.数_0) {
            p = (cast(dchar)(s[++开始]));
        }
    }
    return ·tuple(开始, dot);
}
LostFraction_ trailingHexadecimalFraction(dstring s, ulong digitValue) {
    ulong 开始 = 0;
    dchar p = (cast(dchar)(s[开始]));
    size_t end = s.length;
    uint hexDigit = 0;
    /* If the first trailing digit isn't 0 or 8 we can work out the
       fraction immediately.  */
    if (digitValue > 8) {
        return LostFraction_.lfMoreThanHalf;
    }
    else if (digitValue < 8 && digitValue > 0) {
        return LostFraction_.lfLessThanHalf;
    }
    // Otherwise we need to find the first non-zero digit.
    while(开始 != end && (p == 字符_.数_0 || p == 字符_.点号)) {
        p = (cast(dchar)(s[++开始]));
    }
    if (开始 == end) {
        throw new Throwable(·to!(string)(("Invalid trailing hexadecimal fraction!"d)));
    }
    hexDigit = hexDigitValue(p);
    /* If we ran off the end it is exactly zero or one-half, otherwise
       a little more.  */
    if (hexDigit == -1u) {
        return digitValue == 0 ? LostFraction_.lfExactlyZero : LostFraction_.lfExactlyHalf;
    }
    else {
        return digitValue == 0 ? LostFraction_.lfLessThanHalf : LostFraction_.lfMoreThanHalf;
    }
}
int totalExponent(dstring s, ref int exponentAdjustment) {
    ulong 开始 = 0;
    size_t end = s.length;
    if (开始 == end) {
        throw new Throwable(·to!(string)(("Exponent has no digits"d)));
    }
    dchar p = (cast(dchar)(s[开始]));
    bool negative = p == 字符_.减号;
    if (p == 字符_.减号 || p == 字符_.加号) {
        p = (cast(dchar)(s[++开始]));
        if (开始 == end) {
            throw new Throwable(·to!(string)(("Exponent has no digits"d)));
        }
    }
    int unsignedExponent = 0;
    bool overflow = false;
    for (; 开始 != end; ++开始) {
        p = (cast(dchar)(s[开始]));
        uint value = .decDigitValue(p);
        if (value >= 10u) {
            throw new Throwable(·to!(string)(("Invalid character in exponent"d)));
        }
        unsignedExponent = unsignedExponent * 10 + value;
        if (unsignedExponent > 32767) {
            overflow = true;
            break;
        }
    }
    if (exponentAdjustment > 32767 || exponentAdjustment < -32768) {
        overflow = true;
    }
    int exponent = 0;
    if (!overflow) {
        exponent = unsignedExponent;
        if (negative) {
            exponent = -exponent;
        }
        exponent += exponentAdjustment;
        if (exponent > 32767 || exponent < -32768) {
            overflow = true;
        }
    }
    if (overflow) {
        exponent = negative ? -32768 : 32767;
    }
    return exponent;
}
APFloat_ APFloat_getInf(FltSemantics_ Sem, bool Negative = false) {
    APFloat_ Val = new APFloat_(Sem);
    Val.makeInf(Negative);
    return Val;
}
APFloat_ APFloat_getNaN(FltSemantics_ Sem, bool Negative = false, ulong payload = ··null!(ulong)) {
    if (payload !is ··null!(ulong)) {
        APInt_ intPayload = new APInt_(64, payload);
        return .APFloat_getQNaN(Sem, Negative, intPayload);
    }
    return .APFloat_getQNaN(Sem, Negative);
}
APFloat_ APFloat_getQNaN(FltSemantics_ Sem, bool Negative = false, APInt_ payload = ··null!(APInt_)) {
    APFloat_ Val = new APFloat_(Sem);
    Val.makeNaN(false, Negative, payload);
    return Val;
}
APFloat_ APFloat_getSNaN(FltSemantics_ Sem, bool Negative = false, APInt_ payload = ··null!(APInt_)) {
    APFloat_ Val = new APFloat_(Sem);
    Val.makeNaN(true, Negative, payload);
    return Val;
}
APFloat_ APFloat_getZero(FltSemantics_ Sem, bool Negative = false) {
    APFloat_ Val = new APFloat_(Sem);
    Val.makeZero(Negative);
    return Val;
}
APFloat_ APFloat_getAllOnesValue(FltSemantics_ Semantics, uint BitWidth) {
    return new APFloat_(Semantics, getAllOnesValue(BitWidth));
}
unittest {
    ulong HexIntToVal(dstring Buffer) {
        ulong Result = 0;
        {
            for (ulong i = 0; i < Buffer.length; ++i) {
                ulong OldRes = Result;
                Result *= 16;
                Result += hexDigitValue(Buffer[i]);
                if (Result < OldRes) { // Uh, oh, overflow detected!!!
                    return 0;
                }
            }
        }
        return Result;
    }
    void main() {
        double f = 3.5;
        ulong n = 字节转换!(ulong, double)(f);
        IEEEFloat_ e2 = new IEEEFloat_(.IEEEdouble(), new APInt_(64, n));
        .·writeln(e2.打印(0, 0, false));
    }
    main();
}
